diff --git a/Docs/BuiltinIndex.md b/Docs/BuiltinIndex.md index d7e83aa46..d991354fd 100644 --- a/Docs/BuiltinIndex.md +++ b/Docs/BuiltinIndex.md @@ -65,6 +65,9 @@ - birdhide - cafe_pub - charging_station + - climbing + - climbing_gym + - climbing_route - defibrillator - drinking_water - entrance @@ -94,6 +97,7 @@ - viewpoint - village_green - watermill + - windturbine @@ -108,7 +112,10 @@ - bicycle_rental - bike_themed_object - cafe_pub + - climbing_club + - climbing_gym - food + - hackerspace - nature_reserve - observation_tower - playground @@ -127,7 +134,10 @@ - bicycle_rental - bike_themed_object - cafe_pub + - climbing_club + - climbing_gym - food + - hackerspace - recycling @@ -143,7 +153,10 @@ - bicycle_rental - bike_themed_object - cafe_pub + - climbing_club + - climbing_gym - food + - hackerspace - recycling @@ -160,6 +173,8 @@ - bike_shop - bike_themed_object - cafe_pub + - climbing_club + - climbing_gym - food @@ -251,6 +266,7 @@ - cafe_pub - defibrillator - food + - hackerspace - observation_tower diff --git a/Docs/FilterFunctionality.gif b/Docs/FilterFunctionality.gif new file mode 100644 index 000000000..69b826dc4 Binary files /dev/null and b/Docs/FilterFunctionality.gif differ diff --git a/Docs/FilteredByDepth.gif b/Docs/FilteredByDepth.gif new file mode 100644 index 000000000..3af61e8d3 Binary files /dev/null and b/Docs/FilteredByDepth.gif differ diff --git a/Docs/Layers/bicycle_rental.md b/Docs/Layers/bicycle_rental.md index 56fb7f63f..196ea87fa 100644 --- a/Docs/Layers/bicycle_rental.md +++ b/Docs/Layers/bicycle_rental.md @@ -94,12 +94,11 @@ The question is **What kind of bicycle rental is this?** - - **This is a shop whose main focus is bicycle rental** corresponds with shop=bicycle_rental&bicycle_rental=shop - - **This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus** corresponds with shop=rental_This option cannot be chosen as answer_ - - **This is a shop which sells or repairs bicycles, but also rents out bicycles** corresponds with service:bicycle:rental=yes&shop=bicycle - - **This is an automated docking station, where a bicycle is mechanically locked into a structure** corresponds with bicycle_rental=docking_station - - **A machine is present which dispenses and accepts keys, eventually after authentication and/or payment. The bicycles are parked nearby** corresponds with bicycle_rental=key_dispensing_machine - - **This is a dropoff point: a designated bicycle parking for this cycle rental** corresponds with bicycle_rental=dropoff_point + - **This is a shop whose main focus is bicycle rental** corresponds with shop=rental&bicycle_rental=shop + - **This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus** corresponds with service:bicycle:rental=yes&shop=bicycle + - **This is a shop which sells or repairs bicycles, but also rents out bicycles** corresponds with bicycle_rental=docking_station + - **This is an automated docking station, where a bicycle is mechanically locked into a structure** corresponds with bicycle_rental=key_dispensing_machine + - **A machine is present which dispenses and accepts keys, eventually after authentication and/or payment. The bicycles are parked nearby** corresponds with bicycle_rental=dropoff_point Only visible if `amenity=bicycle_rental` is shown diff --git a/Docs/Making_Your_Own_Theme.md b/Docs/Making_Your_Own_Theme.md index 5279b8b96..7848988d2 100644 --- a/Docs/Making_Your_Own_Theme.md +++ b/Docs/Making_Your_Own_Theme.md @@ -4,6 +4,11 @@ Making your own theme In MapComplete, it is relatively simple to make your own theme. This guide will give some information on how you can do this. +Table of contents: + +1. [Requirements](#requirements) which lists what you should know before starting to create a theme +2. [What is a good theme?](#what-is-a-good-theme) + Requirements ------------ @@ -15,14 +20,217 @@ Before you start, you should have the following qualifications: - You are in contact with your local OpenStreetMap community and do know some other members to discuss tagging and to help testing -If you do not have those qualifications, reach out to the MapComplete community channel +Please, do reach out to the MapComplete community channel on [Telegram](https://t.me/MapComplete) or [Matrix](https://app.element.io/#/room/#MapComplete:matrix.org). + +What is a good theme? +--------------------- + +A **theme** (or _layout_) is a single map showing one or more layers. +The layers should work together in such a way that they serve a certain **audience**. +You should be able to state in a few sentences whom would be the user of such a map, e.g. + +- a cyclist searching for bike repair +- a thirsty person who needs water +- someone who wants to know what their street is named after +- ... + +Some layers will be useful for many themes (e.g. _drinking water_, _toilets_, _shops_, ...). Due to this, MapComplete supports to reuse already existing official layers into a theme. + +To include an already existing layer, simply type the layer id, e.g.: + +```json +{ + "id": "my-theme", + "title": "My theme for xyz", + "...": "...", + "layers": [ + { + "id": "my super-awesome new layer" + }, + "bench", + "shops", + "drinking_water", + "toilet" + ] +} +``` + +Note that it is good practice to use an existing layer and to tweak it: + +```json +{ + "id": "my super awesome theme", + "...": "...", + "layers": [ + { + "builtin": [ + "toilet", + "bench" + ], + "override": { + "#": "Override is a section which copies all the keys here and 'pastes' them into the existing layers. For example, the 'minzoom' defined here will redifine the minzoom of 'toilet' and 'bench'", + "minzoom": 17, + "#0": "Appending to lists is supported to, e.g. to add an extra question", + "tagRenderings+": [ + { + "id": "new-question", + "question": "What is ?", + "render": "{property}", + "...": "..." + } + ], + "#1": "Note that paths will be followed: the below block will add/change the icon of the layer, without changing the other properties of the first tag rendering. (Assumption: the first mapRendering is the icon rendering)", + "mapRendering": [ + { + "icon": { + "render": "new-icon.svg" + } + } + ] + } + } + ] +} + +``` + +### What is a good layer? + +A good layer is layer which shows **all** objects of a certain type, e.g. **all** shops, **all** restaurants, ... + +It asks some relevant questions, with the most important and easiests questions first. + +#### Don't: use a layer to filter + +**Do not define a layer which filters on an attribute**, such as all restaurants with a vegetarian diet, all shops which accept bitcoin. +This makes _addition_ of new points difficult as information might not yet be known. Conser the following situation: + +1. A theme defines a layer `vegetarian restaurants`, which matches `amenity=restaurant` & `diet:vegetarian=yes`. +2. An object exists in OSM with `amenity=restaurant`;`name=Fancy Food`;`diet:vegan=yes`;`phone=...`;... +3. A contributor visits the themes and will notice that _Fancy Food_ is missing +4. The contributor will add _Fancy Food_ +5. There are now **two** Fancy Food objects in OSM. + +Instead, use the filter functionality instead. This can be used from the layer to hide some objects based on their properties. +When the contributor wants to add a new point, they'll be notified that some features might be hidden and only be allowed to add a new point when the points are shown. + +![](./FilterFunctionality.gif) + +```json +{ + "id": "my awesome layer", + "tagRenderings": "... some relevant attributes and questions ...", + "mapRenderings": "... display on the map ... ", + "filter": [ + { + "id": "vegetarian", + "options": [ + { + "question": { + "en": "Has a vegetarian menu" + }, + "osmTags": { + "or": [ + "diet:vegetarian=yes", + "diet:vegetarian=only", + "diet:vegan=yes", + "diet:vegan=only" + ] + } + } + ] + } + ] +} +``` + +If you want to show only features of a certain type, there is a workaround. +For example, the [fritures map](https://mapcomplete.osm.be/fritures.html?z=1&welcome-control-toggle=true) will show french fries shop, aka every `amenity~fast_food|restaurant` with `cuisine=friture`. +However, quite a few fritures are already mapped as fastfood but have their `cuisine`-tag missing (or misspelled). + +There is a workaround for this: show **all** food related items at zoomlevel 19 (or higher), and only show the fritures when zoomed out. + +In order to achieve this: + +1. The layer 'food' is defined in a separate file and reused +2. The layer food is imported in the theme 'fritures'. With 'override', some properties are changed, namely: + - The `osmTags` are overwritten: `cuisine=friture` is now required + - The presets are overwritten and _disabled_ + - The _id_ and _name_ of the layer are changed +3. The layer `food` is imported _a second time_, but now the minzoom is set to `19`. This will show _all_ restaurants. + +In case of a friture which is already added as fastfood, they'll see the fastfood popup instead of adding a new item: + +![](./FilteredByDepth.gif) + +```json +{ + "layers": [ + { + "builtin": "food", + "override": { + "id": "friture", + "name": { + "en": "Fries shop" + }, + "=presets": [], + "source": { + "=osmTags": { + "and": [ + "cuisine=friture", + { + "or": [ + "amenity=fast_food", + "amenity=restaurant" + ] + } + ] + } + } + } + }, + { + "builtin": "food", + "override": { + "minzoom": 19, + "filter": null, + "name": null + } + } + ] +} +``` + + +### What is a good question and tagrendering? + +A tagrendering maps an attribute onto a piece of human readable text. +These should be **full sentences**, e.g. `"render": "The maximum speed of this road is {maxspeed} km/h"` + +In some cases, there might be some predifined special values as mappings, such as `"mappings": [{"if": "maxspeed=30", "then": "The maxspeed is 30km/h"}]` + +The question then follows logically: `{"question": "What is the maximum allowed speed for this road, in km/h?"}` +At last, you'll also want to say that the user can type an answer too and that it has to be a number: `"freeform":{"key": "maxspeed","type":"pnat"}`. + +The entire tagRendering will thus be: + +```json +{ + "question": "What is the maximum allowed speed for this road, in km/h?", + "render": "The maximum speed of this road is {maxspeed} km/h", + "freeform":{"key": "maxspeed","type":"pnat"}, + "mappings": [{"if": "maxspeed=30", "then": "The maxspeed is 30km/h"}] +} +``` + + The template ------------ -[A basic template is availalbe here](https://github.com/pietervdvn/MapComplete/blob/develop/Docs/theme-template.json) +[A basic template is available here](https://github.com/pietervdvn/MapComplete/blob/develop/Docs/theme-template.json) The custom theme generator -------------------------- @@ -229,18 +437,21 @@ disregarding other properties. One should not make one layer for benches with a backrest and one layer for benches without. This is confusing for users and poses problems: what if the backrest status is unknown? What if it is some weird value? Also, it isn't possible to ' -move' an attribute to another layer. +move' a feature to another layer. Instead, make one layer for one kind of object and change the icon based on attributes. -### Using layers as filters - -Using layers as filters - this doesn't work! - -Use the `filter`-functionality instead. - ### Not reading the theme JSON specs There are a few advanced features to do fancy stuff available, which are documented only in the spec above - for example, reusing background images and substituting the colours or HTML rendering. If you need advanced stuff, read it through! + +### Forgetting adjacent concepts + +Some new contributors might add a POI to indicate something that resembles it, but quite isn't. + +For example, if they are only offered a layer with public bookcases, they might map their local library with a public bookcase. +The perfect solution for this is to provide both the library-layer and public bookcases layer - but this requires having both layers. + +A good solution is to clearly explain what a certain feature is and what it is not. \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_bicycle_rental.json b/Docs/TagInfo/mapcomplete_bicycle_rental.json index 5a7fa2210..83fec1d06 100644 --- a/Docs/TagInfo/mapcomplete_bicycle_rental.json +++ b/Docs/TagInfo/mapcomplete_bicycle_rental.json @@ -46,42 +46,37 @@ }, { "key": "shop", - "description": "Layer 'Bicycle rental' shows shop=bicycle_rental&bicycle_rental=shop with a fixed text, namely 'This is a shop whose main focus is bicycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", - "value": "bicycle_rental" - }, - { - "key": "bicycle_rental", - "description": "Layer 'Bicycle rental' shows shop=bicycle_rental&bicycle_rental=shop with a fixed text, namely 'This is a shop whose main focus is bicycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", - "value": "shop" - }, - { - "key": "shop", - "description": "Layer 'Bicycle rental' shows shop=rental with a fixed text, namely 'This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus' (in the MapComplete.osm.be theme 'Bicycle rental')", + "description": "Layer 'Bicycle rental' shows shop=rental&bicycle_rental=shop with a fixed text, namely 'This is a shop whose main focus is bicycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", "value": "rental" }, + { + "key": "bicycle_rental", + "description": "Layer 'Bicycle rental' shows shop=rental&bicycle_rental=shop with a fixed text, namely 'This is a shop whose main focus is bicycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", + "value": "shop" + }, { "key": "service:bicycle:rental", - "description": "Layer 'Bicycle rental' shows service:bicycle:rental=yes&shop=bicycle with a fixed text, namely 'This is a shop which sells or repairs bicycles, but also rents out bicycles' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", + "description": "Layer 'Bicycle rental' shows service:bicycle:rental=yes&shop=bicycle with a fixed text, namely 'This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", "value": "yes" }, { "key": "shop", - "description": "Layer 'Bicycle rental' shows service:bicycle:rental=yes&shop=bicycle with a fixed text, namely 'This is a shop which sells or repairs bicycles, but also rents out bicycles' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", + "description": "Layer 'Bicycle rental' shows service:bicycle:rental=yes&shop=bicycle with a fixed text, namely 'This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", "value": "bicycle" }, { "key": "bicycle_rental", - "description": "Layer 'Bicycle rental' shows bicycle_rental=docking_station with a fixed text, namely 'This is an automated docking station, where a bicycle is mechanically locked into a structure' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", + "description": "Layer 'Bicycle rental' shows bicycle_rental=docking_station with a fixed text, namely 'This is a shop which sells or repairs bicycles, but also rents out bicycles' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", "value": "docking_station" }, { "key": "bicycle_rental", - "description": "Layer 'Bicycle rental' shows bicycle_rental=key_dispensing_machine with a fixed text, namely 'A machine is present which dispenses and accepts keys, eventually after authentication and/or payment. The bicycles are parked nearby' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", + "description": "Layer 'Bicycle rental' shows bicycle_rental=key_dispensing_machine with a fixed text, namely 'This is an automated docking station, where a bicycle is mechanically locked into a structure' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", "value": "key_dispensing_machine" }, { "key": "bicycle_rental", - "description": "Layer 'Bicycle rental' shows bicycle_rental=dropoff_point with a fixed text, namely 'This is a dropoff point: a designated bicycle parking for this cycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", + "description": "Layer 'Bicycle rental' shows bicycle_rental=dropoff_point with a fixed text, namely 'A machine is present which dispenses and accepts keys, eventually after authentication and/or payment. The bicycles are parked nearby' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle rental')", "value": "dropoff_point" }, { diff --git a/Docs/TagInfo/mapcomplete_personal.json b/Docs/TagInfo/mapcomplete_personal.json index 3e02dc999..8850e33e1 100644 --- a/Docs/TagInfo/mapcomplete_personal.json +++ b/Docs/TagInfo/mapcomplete_personal.json @@ -607,42 +607,37 @@ }, { "key": "shop", - "description": "Layer 'Bicycle rental' shows shop=bicycle_rental&bicycle_rental=shop with a fixed text, namely 'This is a shop whose main focus is bicycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "bicycle_rental" - }, - { - "key": "bicycle_rental", - "description": "Layer 'Bicycle rental' shows shop=bicycle_rental&bicycle_rental=shop with a fixed text, namely 'This is a shop whose main focus is bicycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "shop" - }, - { - "key": "shop", - "description": "Layer 'Bicycle rental' shows shop=rental with a fixed text, namely 'This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus' (in the MapComplete.osm.be theme 'Personal theme')", + "description": "Layer 'Bicycle rental' shows shop=rental&bicycle_rental=shop with a fixed text, namely 'This is a shop whose main focus is bicycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "rental" }, + { + "key": "bicycle_rental", + "description": "Layer 'Bicycle rental' shows shop=rental&bicycle_rental=shop with a fixed text, namely 'This is a shop whose main focus is bicycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "value": "shop" + }, { "key": "service:bicycle:rental", - "description": "Layer 'Bicycle rental' shows service:bicycle:rental=yes&shop=bicycle with a fixed text, namely 'This is a shop which sells or repairs bicycles, but also rents out bicycles' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "description": "Layer 'Bicycle rental' shows service:bicycle:rental=yes&shop=bicycle with a fixed text, namely 'This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "yes" }, { "key": "shop", - "description": "Layer 'Bicycle rental' shows service:bicycle:rental=yes&shop=bicycle with a fixed text, namely 'This is a shop which sells or repairs bicycles, but also rents out bicycles' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "description": "Layer 'Bicycle rental' shows service:bicycle:rental=yes&shop=bicycle with a fixed text, namely 'This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "bicycle" }, { "key": "bicycle_rental", - "description": "Layer 'Bicycle rental' shows bicycle_rental=docking_station with a fixed text, namely 'This is an automated docking station, where a bicycle is mechanically locked into a structure' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "description": "Layer 'Bicycle rental' shows bicycle_rental=docking_station with a fixed text, namely 'This is a shop which sells or repairs bicycles, but also rents out bicycles' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "docking_station" }, { "key": "bicycle_rental", - "description": "Layer 'Bicycle rental' shows bicycle_rental=key_dispensing_machine with a fixed text, namely 'A machine is present which dispenses and accepts keys, eventually after authentication and/or payment. The bicycles are parked nearby' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "description": "Layer 'Bicycle rental' shows bicycle_rental=key_dispensing_machine with a fixed text, namely 'This is an automated docking station, where a bicycle is mechanically locked into a structure' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "key_dispensing_machine" }, { "key": "bicycle_rental", - "description": "Layer 'Bicycle rental' shows bicycle_rental=dropoff_point with a fixed text, namely 'This is a dropoff point: a designated bicycle parking for this cycle rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "description": "Layer 'Bicycle rental' shows bicycle_rental=dropoff_point with a fixed text, namely 'A machine is present which dispenses and accepts keys, eventually after authentication and/or payment. The bicycles are parked nearby' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "dropoff_point" }, { diff --git a/Docs/theme-template.json b/Docs/theme-template.json index 9ead97d56..8d904d0aa 100644 --- a/Docs/theme-template.json +++ b/Docs/theme-template.json @@ -22,9 +22,8 @@ "#": "For more options and configuration, see the documentation in LayoutConfig.json", "#layers": "The list of layers is where most of the content will be. Either reuse an already existing layer by simply calling it's ID or define a whole new layer. An overview of builtin layers is at https://github.com/pietervdvn/MapComplete/blob/develop/Docs/BuiltinLayers.md#normal-layers", "layers": [ - "bench", { - "id": "a singular nound describing the feature, in english", + "id": "a singular noun describing the feature, in english", "source": { "osmTags": { "#": "For a description on which tags are possible, see https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md", diff --git a/Logic/Actors/GeoLocationHandler.ts b/Logic/Actors/GeoLocationHandler.ts index 52f420f20..24e8e5268 100644 --- a/Logic/Actors/GeoLocationHandler.ts +++ b/Logic/Actors/GeoLocationHandler.ts @@ -101,7 +101,6 @@ export default class GeoLocationHandler extends VariableUiElement { const latLonGiven = QueryParameters.wasInitialized("lat") && QueryParameters.wasInitialized("lon") const willFocus = lastClick.map(lastUserRequest => { const timeDiffInited = (new Date().getTime() - initedAt.getTime()) / 1000 - console.log("TimeDiff with initedAtt is ", timeDiffInited) if (!latLonGiven && !autozoomDone && timeDiffInited < Constants.zoomToLocationTimeout) { return true } @@ -109,7 +108,6 @@ export default class GeoLocationHandler extends VariableUiElement { return false; } const timeDiff = (new Date().getTime() - lastUserRequest.getTime()) / 1000 - console.log("TimeDiff with lastClick is ", timeDiff) return timeDiff <= Constants.zoomToLocationTimeout }) @@ -202,7 +200,7 @@ export default class GeoLocationHandler extends VariableUiElement { self.init(true, true); }); - + const doAutoZoomToLocation = !latLonGiven && state.featureSwitchGeolocation.data && state.selectedElement.data !== undefined this.init(false, doAutoZoomToLocation); @@ -363,14 +361,9 @@ export default class GeoLocationHandler extends VariableUiElement { } } if (!inRange) { - console.log( - "Not zooming to GPS location: out of bounds", - b, - location - ); + console.log("Not zooming to GPS location: out of bounds", b, location); } else { const currentZoom = this._leafletMap.data.getZoom() - this._leafletMap.data.setView([location.latitude, location.longitude], Math.max(targetZoom ?? 0, currentZoom)); } } diff --git a/Logic/Actors/TitleHandler.ts b/Logic/Actors/TitleHandler.ts index d20bea7b9..8593ecf18 100644 --- a/Logic/Actors/TitleHandler.ts +++ b/Logic/Actors/TitleHandler.ts @@ -16,7 +16,7 @@ export default class TitleHandler { const currentTitle: UIEventSource = state.selectedElement.map( selected => { const layout = state.layoutToUse - const defaultTitle = Translations.WT(layout?.title)?.txt ?? "MapComplete" + const defaultTitle = layout?.title?.txt ?? "MapComplete" if (selected === undefined) { return defaultTitle diff --git a/Logic/DetermineLayout.ts b/Logic/DetermineLayout.ts index 734988583..b935481e8 100644 --- a/Logic/DetermineLayout.ts +++ b/Logic/DetermineLayout.ts @@ -14,7 +14,6 @@ import {FixLegacyTheme} from "../Models/ThemeConfig/Conversion/LegacyJsonConvert import {LayerConfigJson} from "../Models/ThemeConfig/Json/LayerConfigJson"; import SharedTagRenderings from "../Customizations/SharedTagRenderings"; import * as known_layers from "../assets/generated/known_layers.json" -import {LayoutConfigJson} from "../Models/ThemeConfig/Json/LayoutConfigJson"; import {PrepareTheme} from "../Models/ThemeConfig/Conversion/PrepareTheme"; import * as licenses from "../assets/generated/license_info.json" import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig"; @@ -43,10 +42,6 @@ export default class DetermineLayout { } let layoutId: string = undefined - if (location.href.indexOf("buurtnatuur.be") >= 0) { - layoutId = "buurtnatuur" - } - const path = window.location.pathname.split("/").slice(-1)[0]; if (path !== "theme.html" && path !== "") { @@ -72,7 +67,7 @@ export default class DetermineLayout { public static LoadLayoutFromHash( userLayoutParam: UIEventSource - ): (LayoutConfig & {definition: LayoutConfigJson}) | null { + ): LayoutConfig | null { let hash = location.hash.substr(1); let json: any; @@ -113,9 +108,7 @@ export default class DetermineLayout { const layoutToUse = DetermineLayout.prepCustomTheme(json) userLayoutParam.setData(layoutToUse.id); - const config = new LayoutConfig(layoutToUse, false); - config["definition"] = json - return config + return layoutToUse } catch (e) { console.error(e) if (hash === undefined || hash.length < 10) { @@ -144,7 +137,7 @@ export default class DetermineLayout { .AttachTo("centermessage"); } - private static prepCustomTheme(json: any): LayoutConfigJson { + private static prepCustomTheme(json: any, sourceUrl?: string): LayoutConfig { if(json.layers === undefined && json.tagRenderings !== undefined){ const iconTr = json.mapRendering.map(mr => mr.icon).find(icon => icon !== undefined) @@ -161,7 +154,6 @@ export default class DetermineLayout { } } - const knownLayersDict = new Map() for (const key in known_layers.layers) { const layer = known_layers.layers[key] @@ -172,10 +164,17 @@ export default class DetermineLayout { sharedLayers: knownLayersDict } json = new FixLegacyTheme().convertStrict(json, "While loading a dynamic theme") + const raw = json; + json = new FixImages(DetermineLayout._knownImages).convertStrict(json, "While fixing the images") json = new PrepareTheme(converState).convertStrict(json, "While preparing a dynamic theme") console.log("The layoutconfig is ", json) - return json + + + return new LayoutConfig(json, false, { + definitionRaw: JSON.stringify(raw, null, " "), + definedAtUrl: sourceUrl + }) } private static async LoadRemoteTheme(link: string): Promise { @@ -190,8 +189,7 @@ export default class DetermineLayout { try { parsed.id = link; console.log("Loaded remote link:", link) - const layoutToUse = DetermineLayout.prepCustomTheme(parsed) - return new LayoutConfig(layoutToUse, false) + return DetermineLayout.prepCustomTheme(parsed, link) } catch (e) { console.error(e) DetermineLayout.ShowErrorOnCustomTheme( diff --git a/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts b/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts index 5349d8d43..1f5d8cbb4 100644 --- a/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts +++ b/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts @@ -1,5 +1,5 @@ /** - * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indiciates with what renderConfig it should be rendered. + * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indicates with what renderConfig it should be rendered. */ import {UIEventSource} from "../../UIEventSource"; import {GeoOperations} from "../../GeoOperations"; @@ -11,22 +11,25 @@ export default class RenderingMultiPlexerFeatureSource { public readonly features: UIEventSource<(any & { pointRenderingIndex: number | undefined, lineRenderingIndex: number | undefined })[]>; constructor(upstream: FeatureSource, layer: LayerConfig) { + + const pointRenderObjects: { rendering: PointRenderingConfig, index: number }[] = layer.mapRendering.map((r, i) => ({ + rendering: r, + index: i + })) + const pointRenderings = pointRenderObjects.filter(r => r.rendering.location.has("point")) + const centroidRenderings = pointRenderObjects.filter(r => r.rendering.location.has("centroid")) + const projectedCentroidRenderings = pointRenderObjects.filter(r => r.rendering.location.has("projected_centerpoint")) + const startRenderings = pointRenderObjects.filter(r => r.rendering.location.has("start")) + const endRenderings = pointRenderObjects.filter(r => r.rendering.location.has("end")) + const hasCentroid = centroidRenderings.length > 0 || projectedCentroidRenderings.length > 0 + const lineRenderObjects = layer.lineRendering + this.features = upstream.features.map( features => { if (features === undefined) { return; } - const pointRenderObjects: { rendering: PointRenderingConfig, index: number }[] = layer.mapRendering.map((r, i) => ({ - rendering: r, - index: i - })) - const pointRenderings = pointRenderObjects.filter(r => r.rendering.location.has("point")) - const centroidRenderings = pointRenderObjects.filter(r => r.rendering.location.has("centroid")) - const startRenderings = pointRenderObjects.filter(r => r.rendering.location.has("start")) - const endRenderings = pointRenderObjects.filter(r => r.rendering.location.has("end")) - - const lineRenderObjects = layer.lineRendering const withIndex: (any & { pointRenderingIndex: number | undefined, lineRenderingIndex: number | undefined, multiLineStringIndex: number | undefined })[] = []; @@ -55,12 +58,25 @@ export default class RenderingMultiPlexerFeatureSource { } } else { // This is a a line: add the centroids - for (const rendering of centroidRenderings) { - addAsPoint(feat, rendering, GeoOperations.centerpointCoordinates(feat)) + let centerpoint: [number, number] = undefined; + let projectedCenterPoint : [number, number] = undefined + if(hasCentroid){ + centerpoint = GeoOperations.centerpointCoordinates(feat) + if(projectedCentroidRenderings.length > 0){ + projectedCenterPoint = <[number,number]> GeoOperations.nearestPoint(feat, centerpoint).geometry.coordinates + } } + for (const rendering of centroidRenderings) { + addAsPoint(feat, rendering, centerpoint) + } + if (feat.geometry.type === "LineString") { + for (const rendering of projectedCentroidRenderings) { + addAsPoint(feat, rendering, projectedCenterPoint) + } + // Add start- and endpoints const coordinates = feat.geometry.coordinates for (const rendering of startRenderings) { @@ -71,6 +87,10 @@ export default class RenderingMultiPlexerFeatureSource { addAsPoint(feat, rendering, coordinate) } + }else{ + for (const rendering of projectedCentroidRenderings) { + addAsPoint(feat, rendering, centerpoint) + } } // AT last, add it 'as is' to what we should render diff --git a/Logic/Osm/OsmPreferences.ts b/Logic/Osm/OsmPreferences.ts index 7e06bdfc6..dc9b5c50e 100644 --- a/Logic/Osm/OsmPreferences.ts +++ b/Logic/Osm/OsmPreferences.ts @@ -76,9 +76,9 @@ export class OsmPreferences { function updateData(l: number) { - if (l === undefined) { - source.setData(undefined); - return; + if(Object.keys(self.preferences.data).length === 0){ + // The preferences are still empty - they are not yet updated, so we delay updating for now + return } const prefsCount = Number(l); if (prefsCount > 100) { @@ -86,7 +86,11 @@ export class OsmPreferences { } let str = ""; for (let i = 0; i < prefsCount; i++) { - str += self.GetPreference(allStartWith + "-" + i, "").data; + const key = allStartWith + "-" + i + if(self.preferences.data[key] === undefined){ + console.warn("Detected a broken combined preference:", key, "is undefined", self.preferences) + } + str += self.preferences.data[key] ?? ""; } source.setData(str); @@ -95,7 +99,9 @@ export class OsmPreferences { length.addCallback(l => { updateData(Number(l)); }); - updateData(Number(length.data)); + this.preferences.addCallbackAndRun(_ => { + updateData(Number(length.data)); + }) return source; } @@ -127,7 +133,8 @@ export class OsmPreferences { public ClearPreferences() { let isRunning = false; const self = this; - this.preferences.addCallbackAndRun(prefs => { + this.preferences.addCallback(prefs => { + console.log("Cleaning preferences...") if (Object.keys(prefs).length == 0) { return; } @@ -135,19 +142,17 @@ export class OsmPreferences { return } isRunning = true - const prefixes = ["mapcomplete-installed-theme", "mapcomplete-installed-themes-", "mapcomplete-current-open-changeset", "mapcomplete-personal-theme-layer"] + const prefixes = ["mapcomplete-"] for (const key in prefs) { - for (const prefix of prefixes) { - if (key.startsWith(prefix)) { - console.log("Clearing ", key) - self.GetPreference(key, "").setData("") + const matches = prefixes.some(prefix => key.startsWith(prefix)) + if (matches) { + console.log("Clearing ", key) + self.GetPreference(key, "").setData("") - } } } isRunning = false; - return true; - + return; }) } @@ -173,7 +178,6 @@ export class OsmPreferences { // For differing values, the server overrides local changes self.preferenceSources.forEach((preference, key) => { const osmValue = self.preferences.data[key] - console.log("Sending value to osm:", key," osm has: ", osmValue, " local has: ", preference.data) if(osmValue === undefined && preference.data !== undefined){ // OSM doesn't know this value yet self.UploadPreference(key, preference.data) diff --git a/Logic/Tags/And.ts b/Logic/Tags/And.ts index 5a2eecbc9..340c2161f 100644 --- a/Logic/Tags/And.ts +++ b/Logic/Tags/And.ts @@ -8,6 +8,13 @@ export class And extends TagsFilter { super(); this.and = and } + + public static construct(and: TagsFilter[]): TagsFilter{ + if(and.length === 1){ + return and[0] + } + return new And(and) + } private static combine(filter: string, choices: string[]): string[] { const values = []; @@ -45,7 +52,7 @@ export class And extends TagsFilter { * import {RegexTag} from "./RegexTag"; * * const and = new And([new Tag("boundary","protected_area"), new RegexTag("protect_class","98",true)]) - * and.asOverpass() // => [ "[\"boundary\"=\"protected_area\"][\"protect_class\"!~\"^98$\"]" ] + * and.asOverpass() // => [ "[\"boundary\"=\"protected_area\"][\"protect_class\"!=\"98\"]" ] */ asOverpass(): string[] { let allChoices: string[] = null; @@ -87,17 +94,17 @@ export class And extends TagsFilter { * ]) * const t1 = new And([new Tag("valves", "A")]) * const t2 = new And([new Tag("valves", "B")]) - * t0.isEquivalent(t0) // => true - * t1.isEquivalent(t1) // => true - * t2.isEquivalent(t2) // => true - * t0.isEquivalent(t1) // => false - * t0.isEquivalent(t2) // => false - * t1.isEquivalent(t0) // => false - * t1.isEquivalent(t2) // => false - * t2.isEquivalent(t0) // => false - * t2.isEquivalent(t1) // => false + * t0.shadows(t0) // => true + * t1.shadows(t1) // => true + * t2.shadows(t2) // => true + * t0.shadows(t1) // => false + * t0.shadows(t2) // => false + * t1.shadows(t0) // => false + * t1.shadows(t2) // => false + * t2.shadows(t0) // => false + * t2.shadows(t1) // => false */ - isEquivalent(other: TagsFilter): boolean { + shadows(other: TagsFilter): boolean { if (!(other instanceof And)) { return false; } @@ -105,7 +112,7 @@ export class And extends TagsFilter { for (const selfTag of this.and) { let matchFound = false; for (const otherTag of other.and) { - matchFound = selfTag.isEquivalent(otherTag); + matchFound = selfTag.shadows(otherTag); if (matchFound) { break; } @@ -118,7 +125,7 @@ export class And extends TagsFilter { for (const otherTag of other.and) { let matchFound = false; for (const selfTag of this.and) { - matchFound = selfTag.isEquivalent(otherTag); + matchFound = selfTag.shadows(otherTag); if (matchFound) { break; } @@ -148,23 +155,90 @@ export class And extends TagsFilter { return result; } + /** + * IN some contexts, some expressions can be considered true, e.g. + * (X=Y | (A=B & X=Y)) + * ^---------^ + * When the evaluation hits (A=B & X=Y), we know _for sure_ that X=Y does _not_ match, as it would have matched the first clause otherwise. + * This means that the entire 'AND' is considered FALSE + * + * new And([ new Tag("key","value") ,new Tag("other_key","value")]).removePhraseConsideredKnown(new Tag("key","value"), true) // => new Tag("other_key","value") + * new And([ new Tag("key","value") ,new Tag("other_key","value")]).removePhraseConsideredKnown(new Tag("key","value"), false) // => false + * new And([ new RegexTag("key",/^..*$/) ,new Tag("other_key","value")]).removePhraseConsideredKnown(new Tag("key","value"), true) // => new Tag("other_key","value") + * new And([ new Tag("key","value") ]).removePhraseConsideredKnown(new Tag("key","value"), true) // => true + * + * // should remove 'club~*' if we know that 'club=climbing' + * const expr = TagUtils.Tag({and: ["sport=climbing", {or:["club~*", "office~*"]}]} ) + * expr.removePhraseConsideredKnown(new Tag("club","climbing"), true) // => new Tag("sport","climbing") + * + * const expr = TagUtils.Tag({and: ["sport=climbing", {or:["club~*", "office~*"]}]} ) + * expr.removePhraseConsideredKnown(new Tag("club","climbing"), false) // => expr + */ + removePhraseConsideredKnown(knownExpression: TagsFilter, value: boolean): TagsFilter | boolean { + const newAnds: TagsFilter[] = [] + for (const tag of this.and) { + if(tag instanceof And){ + throw "Optimize expressions before using removePhraseConsideredKnown" + } + if(tag instanceof Or){ + const r = tag.removePhraseConsideredKnown(knownExpression, value) + if(r === true){ + continue + } + if(r === false){ + return false; + } + newAnds.push(r) + continue + } + if(value && knownExpression.shadows(tag)){ + /** + * At this point, we do know that 'knownExpression' is true in every case + * As `shadows` does define that 'tag' MUST be true if 'knownExpression' is true, + * we can be sure that 'tag' is true as well. + * + * "True" is the neutral element in an AND, so we can skip the tag + */ + continue + } + if(!value && tag.shadows(knownExpression)){ + + /** + * We know that knownExpression is unmet. + * if the tag shadows 'knownExpression' (which is the case when control flows gets here), + * then tag CANNOT be met too, as known expression is not met. + * + * This implies that 'tag' must be false too! + */ + + // false is the element which absorbs all + return false + } + + newAnds.push(tag) + } + if(newAnds.length === 0){ + return true + } + return And.construct(newAnds) + } + optimize(): TagsFilter | boolean { if(this.and.length === 0){ return true } - const optimized = this.and.map(t => t.optimize()) + const optimizedRaw = this.and.map(t => t.optimize()) + .filter(t => t !== true /* true is the neutral element in an AND, we drop them*/ ) + if(optimizedRaw.some(t => t === false)){ + // We have an AND with a contained false: this is always 'false' + return false; + } + const optimized = optimizedRaw; const newAnds : TagsFilter[] = [] let containedOrs : Or[] = [] for (const tf of optimized) { - if(tf === false){ - return false - } - if(tf === true){ - continue - } - if(tf instanceof And){ newAnds.push(...tf.and) }else if(tf instanceof Or){ @@ -173,27 +247,56 @@ export class And extends TagsFilter { newAnds.push(tf) } } - - containedOrs = containedOrs.filter(ca => { - for (const element of ca.or) { - if(optimized.some(opt => typeof opt !== "boolean" && element.isEquivalent(opt) )){ - // At least one part of the 'OR' is matched by the outer or, so this means that this OR isn't needed at all - // XY & (XY | AB) === XY - return false + + { + let dirty = false; + do { + const cleanedContainedOrs : Or[] = [] + outer: for (let containedOr of containedOrs) { + for (const known of newAnds) { + // input for optimazation: (K=V & (X=Y | K=V)) + // containedOr: (X=Y | K=V) + // newAnds (and thus known): (K=V) --> true + const cleaned = containedOr.removePhraseConsideredKnown(known, true) + if (cleaned === true) { + // The neutral element within an AND + continue outer // skip addition too + } + if (cleaned === false) { + // zero element + return false + } + if (cleaned instanceof Or) { + containedOr = cleaned + continue + } + // the 'or' dissolved into a normal tag -> it has to be added to the newAnds + newAnds.push(cleaned) + dirty = true; // rerun this algo later on + continue outer; + } + cleanedContainedOrs.push(containedOr) } - } - return true; + containedOrs = cleanedContainedOrs + } while(dirty) + } + + + containedOrs = containedOrs.filter(ca => { + const isShadowed = TagUtils.containsEquivalents(newAnds, ca.or) + // If 'isShadowed', then at least one part of the 'OR' is matched by the outer and, so this means that this OR isn't needed at all + // XY & (XY | AB) === XY + return !isShadowed; }) // Extract common keys from the OR if(containedOrs.length === 1){ newAnds.push(containedOrs[0]) - } - if(containedOrs.length > 1){ + }else if(containedOrs.length > 1){ let commonValues : TagsFilter [] = containedOrs[0].or for (let i = 1; i < containedOrs.length && commonValues.length > 0; i++){ const containedOr = containedOrs[i]; - commonValues = commonValues.filter(cv => containedOr.or.some(candidate => candidate.isEquivalent(cv))) + commonValues = commonValues.filter(cv => containedOr.or.some(candidate => candidate.shadows(cv))) } if(commonValues.length === 0){ newAnds.push(...containedOrs) @@ -201,19 +304,11 @@ export class And extends TagsFilter { const newOrs: TagsFilter[] = [] for (const containedOr of containedOrs) { const elements = containedOr.or - .filter(candidate => !commonValues.some(cv => cv.isEquivalent(candidate))) - const or = new Or(elements).optimize() - if(or === true){ - // neutral element - continue - } - if(or === false){ - return false - } - newOrs.push(or) + .filter(candidate => !commonValues.some(cv => cv.shadows(candidate))) + newOrs.push(Or.construct(elements)) } - commonValues.push(new And(newOrs)) + commonValues.push(And.construct(newOrs)) const result = new Or(commonValues).optimize() if(result === false){ return false @@ -224,16 +319,22 @@ export class And extends TagsFilter { } } } - - if(newAnds.length === 1){ - return newAnds[0] + if(newAnds.length === 0){ + return true } + + if(TagUtils.ContainsOppositeTags(newAnds)){ + return false + } + TagUtils.sortFilters(newAnds, true) - return new And(newAnds) + return And.construct(newAnds) } isNegative(): boolean { return !this.and.some(t => !t.isNegative()); } + + } \ No newline at end of file diff --git a/Logic/Tags/ComparingTag.ts b/Logic/Tags/ComparingTag.ts index 6b790311b..fa543350f 100644 --- a/Logic/Tags/ComparingTag.ts +++ b/Logic/Tags/ComparingTag.ts @@ -23,7 +23,7 @@ export default class ComparingTag implements TagsFilter { throw "A comparable tag can not be used as overpass filter" } - isEquivalent(other: TagsFilter): boolean { + shadows(other: TagsFilter): boolean { return other === this; } diff --git a/Logic/Tags/Or.ts b/Logic/Tags/Or.ts index 4d3ab20e0..b2aa7ec27 100644 --- a/Logic/Tags/Or.ts +++ b/Logic/Tags/Or.ts @@ -11,6 +11,14 @@ export class Or extends TagsFilter { this.or = or; } + public static construct(or: TagsFilter[]): TagsFilter{ + if(or.length === 1){ + return or[0] + } + return new Or(or) + } + + matchesProperties(properties: any): boolean { for (const tagsFilter of this.or) { if (tagsFilter.matchesProperties(properties)) { @@ -28,7 +36,7 @@ export class Or extends TagsFilter { * * const and = new And([new Tag("boundary","protected_area"), new RegexTag("protect_class","98",true)]) * const or = new Or([and, new Tag("leisure", "nature_reserve"]) - * or.asOverpass() // => [ "[\"boundary\"=\"protected_area\"][\"protect_class\"!~\"^98$\"]", "[\"leisure\"=\"nature_reserve\"]" ] + * or.asOverpass() // => [ "[\"boundary\"=\"protected_area\"][\"protect_class\"!=\"98\"]", "[\"leisure\"=\"nature_reserve\"]" ] * * // should fuse nested ors into a single list * const or = new Or([new Tag("key","value"), new Or([new Tag("key1","value1"), new Tag("key2","value2")])]) @@ -51,14 +59,14 @@ export class Or extends TagsFilter { return false; } - isEquivalent(other: TagsFilter): boolean { + shadows(other: TagsFilter): boolean { if (other instanceof Or) { for (const selfTag of this.or) { let matchFound = false; for (let i = 0; i < other.or.length && !matchFound; i++) { let otherTag = other.or[i]; - matchFound = selfTag.isEquivalent(otherTag); + matchFound = selfTag.shadows(otherTag); } if (!matchFound) { return false; @@ -85,45 +93,127 @@ export class Or extends TagsFilter { return result; } + /** + * IN some contexts, some expressions can be considered true, e.g. + * (X=Y & (A=B | X=Y)) + * ^---------^ + * When the evaluation hits (A=B | X=Y), we know _for sure_ that X=Y _does match, as it would have failed the first clause otherwise. + * This means we can safely ignore this in the OR + * + * new Or([ new Tag("key","value") ,new Tag("other_key","value")]).removePhraseConsideredKnown(new Tag("key","value"), true) // =>true + * new Or([ new Tag("key","value") ,new Tag("other_key","value")]).removePhraseConsideredKnown(new Tag("key","value"), false) // => new Tag("other_key","value") + * new Or([ new Tag("key","value") ]).removePhraseConsideredKnown(new Tag("key","value"), true) // => true + * new Or([ new Tag("key","value") ]).removePhraseConsideredKnown(new Tag("key","value"), false) // => false + * new Or([new RegexTag("x", "y", true),new RegexTag("c", "d")]).removePhraseConsideredKnown(new Tag("foo","bar"), false) // => new Or([new RegexTag("x", "y", true),new RegexTag("c", "d")]) + */ + removePhraseConsideredKnown(knownExpression: TagsFilter, value: boolean): TagsFilter | boolean { + const newOrs: TagsFilter[] = [] + for (const tag of this.or) { + if(tag instanceof Or){ + throw "Optimize expressions before using removePhraseConsideredKnown" + } + if(tag instanceof And){ + const r = tag.removePhraseConsideredKnown(knownExpression, value) + if(r === false){ + continue + } + if(r === true){ + return true; + } + newOrs.push(r) + continue + } + if(value && knownExpression.shadows(tag)){ + /** + * At this point, we do know that 'knownExpression' is true in every case + * As `shadows` does define that 'tag' MUST be true if 'knownExpression' is true, + * we can be sure that 'tag' is true as well. + * + * "True" is the absorbing element in an OR, so we can return true + */ + return true; + } + if(!value && tag.shadows(knownExpression)){ + + /** + * We know that knownExpression is unmet. + * if the tag shadows 'knownExpression' (which is the case when control flows gets here), + * then tag CANNOT be met too, as known expression is not met. + * + * This implies that 'tag' must be false too! + * false is the neutral element in an OR + */ + continue + } + newOrs.push(tag) + } + if(newOrs.length === 0){ + return false + } + return Or.construct(newOrs) + } + optimize(): TagsFilter | boolean { if(this.or.length === 0){ return false; } - const optimized = this.or.map(t => t.optimize()) + const optimizedRaw = this.or.map(t => t.optimize()) + .filter(t => t !== false /* false is the neutral element in an OR, we drop them*/ ) + if(optimizedRaw.some(t => t === true)){ + // We have an OR with a contained true: this is always 'true' + return true; + } + const optimized = optimizedRaw; + const newOrs : TagsFilter[] = [] - let containedAnds : And[] = [] for (const tf of optimized) { - if(tf === true){ - return true - } - if(tf === false){ - continue - } - if(tf instanceof Or){ + // expand all the nested ors... newOrs.push(...tf.or) }else if(tf instanceof And){ + // partition of all the ands containedAnds.push(tf) } else { newOrs.push(tf) } } - containedAnds = containedAnds.filter(ca => { - for (const element of ca.and) { - if(optimized.some(opt => typeof opt !== "boolean" && element.isEquivalent(opt) )){ - // At least one part of the 'AND' is matched by the outer or, so this means that this OR isn't needed at all - // XY | (XY & AB) === XY - return false + { + let dirty = false; + do { + const cleanedContainedANds : And[] = [] + outer: for (let containedAnd of containedAnds) { + for (const known of newOrs) { + // input for optimazation: (K=V | (X=Y & K=V)) + // containedAnd: (X=Y & K=V) + // newOrs (and thus known): (K=V) --> false + const cleaned = containedAnd.removePhraseConsideredKnown(known, false) + if (cleaned === false) { + // The neutral element within an OR + continue outer // skip addition too + } + if (cleaned === true) { + // zero element + return true + } + if (cleaned instanceof And) { + containedAnd = cleaned + continue // clean up with the other known values + } + // the 'and' dissolved into a normal tag -> it has to be added to the newOrs + newOrs.push(cleaned) + dirty = true; // rerun this algo later on + continue outer; + } + cleanedContainedANds.push(containedAnd) } - } - return true; - }) - + containedAnds = cleanedContainedANds + } while(dirty) + } // Extract common keys from the ANDS if(containedAnds.length === 1){ newOrs.push(containedAnds[0]) @@ -131,40 +221,46 @@ export class Or extends TagsFilter { let commonValues : TagsFilter [] = containedAnds[0].and for (let i = 1; i < containedAnds.length && commonValues.length > 0; i++){ const containedAnd = containedAnds[i]; - commonValues = commonValues.filter(cv => containedAnd.and.some(candidate => candidate.isEquivalent(cv))) + commonValues = commonValues.filter(cv => containedAnd.and.some(candidate => candidate.shadows(cv))) } if(commonValues.length === 0){ newOrs.push(...containedAnds) }else{ const newAnds: TagsFilter[] = [] for (const containedAnd of containedAnds) { - const elements = containedAnd.and.filter(candidate => !commonValues.some(cv => cv.isEquivalent(candidate))) - newAnds.push(new And(elements)) + const elements = containedAnd.and.filter(candidate => !commonValues.some(cv => cv.shadows(candidate))) + newAnds.push(And.construct(elements)) } - commonValues.push(new Or(newAnds)) + commonValues.push(Or.construct(newAnds)) const result = new And(commonValues).optimize() if(result === true){ return true }else if(result === false){ // neutral element: skip }else{ - newOrs.push(new And(commonValues)) + newOrs.push(And.construct(commonValues)) } } } - if(newOrs.length === 1){ - return newOrs[0] + if(newOrs.length === 0){ + return false } + + if(TagUtils.ContainsOppositeTags(newOrs)){ + return true + } + TagUtils.sortFilters(newOrs, false) - return new Or(newOrs) + return Or.construct(newOrs) } isNegative(): boolean { return this.or.some(t => t.isNegative()); } + } diff --git a/Logic/Tags/RegexTag.ts b/Logic/Tags/RegexTag.ts index 8a4c7ad3b..a5db5a77f 100644 --- a/Logic/Tags/RegexTag.ts +++ b/Logic/Tags/RegexTag.ts @@ -10,13 +10,6 @@ export class RegexTag extends TagsFilter { constructor(key: string | RegExp, value: RegExp | string, invert: boolean = false) { super(); this.key = key; - if (typeof value === "string") { - if (value.indexOf("^") < 0 && value.indexOf("$") < 0) { - value = "^" + value + "$" - } - value = new RegExp(value) - } - this.value = value; this.invert = invert; this.matchesEmpty = RegexTag.doesMatch("", this.value); @@ -79,14 +72,14 @@ export class RegexTag extends TagsFilter { /** * Checks if this tag matches the given properties * - * const isNotEmpty = new RegexTag("key","^$", true); + * const isNotEmpty = new RegexTag("key",/^$/, true); * isNotEmpty.matchesProperties({"key": "value"}) // => true * isNotEmpty.matchesProperties({"key": "other_value"}) // => true * isNotEmpty.matchesProperties({"key": ""}) // => false * isNotEmpty.matchesProperties({"other_key": ""}) // => false * isNotEmpty.matchesProperties({"other_key": "value"}) // => false * - * const isNotEmpty = new RegexTag("key","^..*$", true); + * const isNotEmpty = new RegexTag("key",/^..*$/, true); * isNotEmpty.matchesProperties({"key": "value"}) // => false * isNotEmpty.matchesProperties({"key": "other_value"}) // => false * isNotEmpty.matchesProperties({"key": ""}) // => true @@ -121,6 +114,9 @@ export class RegexTag extends TagsFilter { * importMatch.matchesProperties({"tags": "amenity=public_bookcase"}) // =>true * importMatch.matchesProperties({"tags": "name=test;amenity=public_bookcase"}) // =>true * importMatch.matchesProperties({"tags": "amenity=bench"}) // =>false + * + * new RegexTag("key","value").matchesProperties({"otherkey":"value"}) // => false + * new RegexTag("key","value",true).matchesProperties({"otherkey":"something"}) // => true */ matchesProperties(tags: any): boolean { if (typeof this.key === "string") { @@ -147,17 +143,87 @@ export class RegexTag extends TagsFilter { asHumanString() { if (typeof this.key === "string") { - return `${this.key}${this.invert ? "!" : ""}~${RegexTag.source(this.value)}`; + const oper = typeof this.value === "string" ? "=" : "~" + return `${this.key}${this.invert ? "!" : ""}${oper}${RegexTag.source(this.value)}`; } return `${this.key.source}${this.invert ? "!" : ""}~~${RegexTag.source(this.value)}` } - isEquivalent(other: TagsFilter): boolean { + /** + * + * new RegexTag("key","value").shadows(new Tag("key","value")) // => true + * new RegexTag("key",/value/).shadows(new RegexTag("key","value")) // => true + * new RegexTag("key",/^..*$/).shadows(new Tag("key","value")) // => false + * new RegexTag("key",/^..*$/).shadows(new Tag("other_key","value")) // => false + * new RegexTag("key", /^a+$/).shadows(new Tag("key", "a")) // => false + * + * + * // should not shadow too eagerly: the first tag might match 'key=abc', the second won't + * new RegexTag("key", /^..*$/).shadows(new Tag("key", "some_value")) // => false + * + * // should handle 'invert' + * new RegexTag("key",/^..*$/, true).shadows(new Tag("key","value")) // => false + * new RegexTag("key",/^..*$/, true).shadows(new Tag("key","")) // => true + * new RegexTag("key","value", true).shadows(new Tag("key","value")) // => false + * new RegexTag("key","value", true).shadows(new Tag("key","some_other_value")) // => false + */ + shadows(other: TagsFilter): boolean { if (other instanceof RegexTag) { - return other.asHumanString() == this.asHumanString(); + if((other.key["source"] ?? other.key) !== (this.key["source"] ?? this.key) ){ + // Keys don't match, never shadowing + return false + } + if((other.value["source"] ?? other.key) === (this.value["source"] ?? this.key) && this.invert == other.invert ){ + // Values (and inverts) match + return true + } + if(typeof other.value ==="string"){ + const valuesMatch = RegexTag.doesMatch(other.value, this.value) + if(!this.invert && !other.invert){ + // this: key~value, other: key=value + return valuesMatch + } + if(this.invert && !other.invert){ + // this: key!~value, other: key=value + return !valuesMatch + } + if(!this.invert && other.invert){ + // this: key~value, other: key!=value + return !valuesMatch + } + if(!this.invert && !other.invert){ + // this: key!~value, other: key!=value + return valuesMatch + } + + } + return false; } if (other instanceof Tag) { - return RegexTag.doesMatch(other.key, this.key) && RegexTag.doesMatch(other.value, this.value); + if(!RegexTag.doesMatch(other.key, this.key)){ + // Keys don't match + return false; + } + + + if(this.value["source"] === "^..*$") { + if(this.invert){ + return other.value === "" + } + return false + } + + if (this.invert) { + /* + * this: "a!=b" + * other: "a=c" + * actual property: a=x + * In other words: shadowing will never occur here + */ + return false; + } + // Unless the values are the same, it is pretty hard to figure out if they are shadowing. This is future work + return (this.value["source"] ?? this.value) === other.value; } return false; } diff --git a/Logic/Tags/SubstitutingTag.ts b/Logic/Tags/SubstitutingTag.ts index 532c2586e..0cb941f14 100644 --- a/Logic/Tags/SubstitutingTag.ts +++ b/Logic/Tags/SubstitutingTag.ts @@ -35,7 +35,7 @@ export default class SubstitutingTag implements TagsFilter { throw "A variable with substitution can not be used to query overpass" } - isEquivalent(other: TagsFilter): boolean { + shadows(other: TagsFilter): boolean { if (!(other instanceof SubstitutingTag)) { return false; } diff --git a/Logic/Tags/Tag.ts b/Logic/Tags/Tag.ts index 9a4919688..1294c6a53 100644 --- a/Logic/Tags/Tag.ts +++ b/Logic/Tags/Tag.ts @@ -88,14 +88,23 @@ export class Tag extends TagsFilter { return true; } - isEquivalent(other: TagsFilter): boolean { - if (other instanceof Tag) { - return this.key === other.key && this.value === other.value; + /** + * // should handle advanced regexes + * new Tag("key", "aaa").shadows(new RegexTag("key", /a+/)) // => true + * new Tag("key","value").shadows(new RegexTag("key", /^..*$/, true)) // => false + * new Tag("key","value").shadows(new Tag("key","value")) // => true + * new Tag("key","some_other_value").shadows(new RegexTag("key", "value", true)) // => true + * new Tag("key","value").shadows(new RegexTag("key", "value", true)) // => false + * new Tag("key","value").shadows(new RegexTag("otherkey", "value", true)) // => false + * new Tag("key","value").shadows(new RegexTag("otherkey", "value", false)) // => false + */ + shadows(other: TagsFilter): boolean { + if(other["key"] !== undefined){ + if(other["key"] !== this.key){ + return false + } } - if (other instanceof RegexTag) { - other.isEquivalent(this); - } - return false; + return other.matchesProperties({[this.key]: this.value}); } usedKeys(): string[] { diff --git a/Logic/Tags/TagUtils.ts b/Logic/Tags/TagUtils.ts index 9ff07534f..064c9cab3 100644 --- a/Logic/Tags/TagUtils.ts +++ b/Logic/Tags/TagUtils.ts @@ -200,15 +200,16 @@ export class TagUtils { * * TagUtils.Tag("key=value") // => new Tag("key", "value") * TagUtils.Tag("key=") // => new Tag("key", "") - * TagUtils.Tag("key!=") // => new RegexTag("key", "^..*$") - * TagUtils.Tag("key!=value") // => new RegexTag("key", /^value$/, true) + * TagUtils.Tag("key!=") // => new RegexTag("key", /^..*$/) + * TagUtils.Tag("key~*") // => new RegexTag("key", /^..*$/) + * TagUtils.Tag("key!=value") // => new RegexTag("key", "value", true) * TagUtils.Tag("vending~.*bicycle_tube.*") // => new RegexTag("vending", /^.*bicycle_tube.*$/) * TagUtils.Tag("x!~y") // => new RegexTag("x", /^y$/, true) * TagUtils.Tag({"and": ["key=value", "x=y"]}) // => new And([new Tag("key","value"), new Tag("x","y")]) * TagUtils.Tag("name~[sS]peelbos.*") // => new RegexTag("name", /^[sS]peelbos.*$/) * TagUtils.Tag("survey:date:={_date:now}") // => new SubstitutingTag("survey:date", "{_date:now}") * TagUtils.Tag("xyz!~\\[\\]") // => new RegexTag("xyz", /^\[\]$/, true) - * TagUtils.Tag("tags~(^|.*;)amenity=public_bookcase($|;.*)") // => new RegexTag("tags", /(^|.*;)amenity=public_bookcase($|;.*)/) + * TagUtils.Tag("tags~(.*;)?amenity=public_bookcase(;.*)?") // => new RegexTag("tags", /^(.*;)?amenity=public_bookcase(;.*)?$/) * TagUtils.Tag("service:bicycle:.*~~*") // => new RegexTag(/^service:bicycle:.*$/, /^..*$/) * * TagUtils.Tag("xyz<5").matchesProperties({xyz: 4}) // => true @@ -306,7 +307,7 @@ export class TagUtils { } return new RegexTag( split[0], - split[1], + new RegExp("^"+ split[1]+"$"), true ); } @@ -338,17 +339,6 @@ export class TagUtils { split[1] = "..*" return new RegexTag(split[0], /^..*$/) } - return new RegexTag( - split[0], - new RegExp("^" + split[1] + "$"), - true - ); - } - if (tag.indexOf("!~") >= 0) { - const split = Utils.SplitFirst(tag, "!~"); - if (split[1] === "*") { - split[1] = "..*" - } return new RegexTag( split[0], split[1], @@ -357,15 +347,18 @@ export class TagUtils { } if (tag.indexOf("~") >= 0) { const split = Utils.SplitFirst(tag, "~"); + let value : string | RegExp = split[1] if (split[1] === "") { throw "Detected a regextag with an empty regex; this is not allowed. Use '" + split[0] + "='instead (at " + context + ")" } - if (split[1] === "*") { - split[1] = "..*" + if (value === "*") { + value = /^..*$/ + }else { + value = new RegExp("^"+value+"$") } return new RegexTag( split[0], - split[1] + value ); } if (tag.indexOf("=") >= 0) { @@ -431,4 +424,94 @@ export class TagUtils { return " (" + joined + ") " } + /** + * Returns 'true' is opposite tags are detected. + * Note that this method will never work perfectly + * + * // should be false for some simple cases + * TagUtils.ContainsOppositeTags([new Tag("key", "value"), new Tag("key0", "value")]) // => false + * TagUtils.ContainsOppositeTags([new Tag("key", "value"), new Tag("key", "value0")]) // => false + * + * // should detect simple cases + * TagUtils.ContainsOppositeTags([new Tag("key", "value"), new RegexTag("key", "value", true)]) // => true + * TagUtils.ContainsOppositeTags([new Tag("key", "value"), new RegexTag("key", /value/, true)]) // => true + */ + public static ContainsOppositeTags(tags: (TagsFilter)[]) : boolean{ + for (let i = 0; i < tags.length; i++){ + const tag = tags[i]; + if(!(tag instanceof Tag || tag instanceof RegexTag)){ + continue + } + for (let j = i + 1; j < tags.length; j++){ + const guard = tags[j]; + if(!(guard instanceof Tag || guard instanceof RegexTag)){ + continue + } + if(guard.key !== tag.key) { + // Different keys: they can _never_ be opposites + continue + } + if((guard.value["source"] ?? guard.value) !== (tag.value["source"] ?? tag.value)){ + // different values: the can _never_ be opposites + continue + } + if( (guard["invert"] ?? false) !== (tag["invert"] ?? false) ) { + // The 'invert' flags are opposite, the key and value is the same for both + // This means we have found opposite tags! + return true + } + } + } + + return false + } + + /** + * Returns a filtered version of 'listToFilter'. + * For a list [t0, t1, t2], If `blackList` contains an equivalent (or broader) match of any `t`, this respective `t` is dropped from the returned list + * Ignores nested ORS and ANDS + * + * TagUtils.removeShadowedElementsFrom([new Tag("key","value")], [new Tag("key","value"), new Tag("other_key","value")]) // => [new Tag("other_key","value")] + */ + public static removeShadowedElementsFrom(blacklist: TagsFilter[], listToFilter: TagsFilter[] ) : TagsFilter[] { + return listToFilter.filter(tf => !blacklist.some(guard => guard.shadows(tf))) + } + + /** + * Returns a filtered version of 'listToFilter', where no duplicates and no equivalents exists. + * + * TagUtils.removeEquivalents([new RegexTag("key", /^..*$/), new Tag("key","value")]) // => [new Tag("key", "value")] + */ + public static removeEquivalents( listToFilter: (Tag | RegexTag)[]) : TagsFilter[] { + const result: TagsFilter[] = [] + outer: for (let i = 0; i < listToFilter.length; i++){ + const tag = listToFilter[i]; + for (let j = 0; j < listToFilter.length; j++){ + if(i === j){ + continue + } + const guard = listToFilter[j]; + if(guard.shadows(tag)) { + // the guard 'kills' the tag: we continue the outer loop without adding the tag + continue outer; + } + } + result.push(tag) + } + return result + } + + /** + * Returns `true` if at least one element of the 'guards' shadows one element of the 'listToFilter'. + * + * TagUtils.containsEquivalents([new Tag("key","value")], [new Tag("key","value"), new Tag("other_key","value")]) // => true + * TagUtils.containsEquivalents([new Tag("key","value")], [ new Tag("other_key","value")]) // => false + * TagUtils.containsEquivalents([new Tag("key","value")], [ new Tag("key","other_value")]) // => false + */ + public static containsEquivalents( guards: TagsFilter[], listToFilter: TagsFilter[] ) : boolean { + return listToFilter.some(tf => guards.some(guard => guard.shadows(tf))) + } + + + } \ No newline at end of file diff --git a/Logic/Tags/TagsFilter.ts b/Logic/Tags/TagsFilter.ts index f3794436f..a99251bb2 100644 --- a/Logic/Tags/TagsFilter.ts +++ b/Logic/Tags/TagsFilter.ts @@ -4,7 +4,11 @@ export abstract class TagsFilter { abstract isUsableAsAnswer(): boolean; - abstract isEquivalent(other: TagsFilter): boolean; + /** + * Indicates some form of equivalency: + * if `this.shadows(t)`, then `this.matches(properties)` implies that `t.matches(properties)` for all possible properties + */ + abstract shadows(other: TagsFilter): boolean; abstract matchesProperties(properties: any): boolean; @@ -30,7 +34,7 @@ export abstract class TagsFilter { * Returns an optimized version (or self) of this tagsFilter */ abstract optimize(): TagsFilter | boolean; - + /** * Returns 'true' if the tagsfilter might select all features (i.e. the filter will return everything from OSM, except a few entries). * diff --git a/Logic/Web/Wikidata.ts b/Logic/Web/Wikidata.ts index dc4329ebd..c32f6b687 100644 --- a/Logic/Web/Wikidata.ts +++ b/Logic/Web/Wikidata.ts @@ -1,6 +1,6 @@ import {Utils} from "../../Utils"; import {UIEventSource} from "../UIEventSource"; -import * as wds from "wikibase-sdk" +import * as wds from "wikidata-sdk" export class WikidataResponse { public readonly id: string @@ -126,13 +126,22 @@ export interface WikidataSearchoptions { maxCount?: 20 | number } +export interface WikidataAdvancedSearchoptions extends WikidataSearchoptions { + instanceOf?: number[]; + notInstanceOf?: number[] +} + + /** * Utility functions around wikidata */ export default class Wikidata { private static readonly _identifierPrefixes = ["Q", "L"].map(str => str.toLowerCase()) - private static readonly _prefixesToRemove = ["https://www.wikidata.org/wiki/Lexeme:", "https://www.wikidata.org/wiki/", "Lexeme:"].map(str => str.toLowerCase()) + private static readonly _prefixesToRemove = ["https://www.wikidata.org/wiki/Lexeme:", + "https://www.wikidata.org/wiki/", + "http://www.wikidata.org/entity/", + "Lexeme:"].map(str => str.toLowerCase()) private static readonly _cache = new Map>() @@ -148,6 +157,52 @@ export default class Wikidata { return src; } + /** + * Given a search text, searches for the relevant wikidata entries, excluding pages "outside of the main tree", e.g. disambiguation pages. + * Optionally, an 'instance of' can be given to limit the scope, e.g. instanceOf:5 (humans) will only search for humans + */ + public static async searchAdvanced(text: string, options: WikidataAdvancedSearchoptions): Promise<{ + id: string, + relevance?: number, + label: string, + description?: string + }[]> { + let instanceOf = "" + if (options?.instanceOf !== undefined && options.instanceOf.length > 0) { + const phrases = options.instanceOf.map(q => `{ ?item wdt:P31/wdt:P279* wd:Q${q}. }`) + instanceOf = "{"+ phrases.join(" UNION ") + "}" + } + const forbidden = (options?.notInstanceOf ?? []) + .concat([17379835]) // blacklist 'wikimedia pages outside of the main knowledge tree', e.g. disambiguation pages + const minusPhrases = forbidden.map(q => `MINUS {?item wdt:P31/wdt:P279* wd:Q${q} .}`) + const sparql = `SELECT * WHERE { + SERVICE wikibase:mwapi { + bd:serviceParam wikibase:api "EntitySearch" . + bd:serviceParam wikibase:endpoint "www.wikidata.org" . + bd:serviceParam mwapi:search "${text}" . + bd:serviceParam mwapi:language "${options.lang}" . + ?item wikibase:apiOutputItem mwapi:item . + ?num wikibase:apiOrdinal true . + bd:serviceParam wikibase:limit ${Math.round((options.maxCount ?? 20) * 1.5) /*Some padding for disambiguation pages */} . + ?label wikibase:apiOutput mwapi:label . + ?description wikibase:apiOutput "@description" . + } + ${instanceOf} + ${minusPhrases.join("\n ")} + } ORDER BY ASC(?num) LIMIT ${options.maxCount ?? 20}` + const url = wds.sparqlQuery(sparql) + + const result = await Utils.downloadJson(url) + /*The full uri of the wikidata-item*/ + + return result.results.bindings.map(({item, label, description, num}) => ({ + relevance: num?.value, + id: item?.value, + label: label?.value, + description: description?.value + })) + } + public static async search( search: string, options?: WikidataSearchoptions, @@ -195,39 +250,28 @@ export default class Wikidata { public static async searchAndFetch( search: string, - options?: WikidataSearchoptions + options?: WikidataAdvancedSearchoptions ): Promise { - const maxCount = options.maxCount // We provide some padding to filter away invalid values - options.maxCount = Math.ceil((options.maxCount ?? 20) * 1.5) - const searchResults = await Wikidata.search(search, options) - const maybeResponses = await Promise.all(searchResults.map(async r => { - try { - return await Wikidata.LoadWikidataEntry(r.id).AsPromise() - } catch (e) { - console.error(e) - return undefined; - } - })) - const responses = maybeResponses - .map(r => r["success"]) - .filter(wd => { - if (wd === undefined) { - return false; + const searchResults = await Wikidata.searchAdvanced(search, options) + const maybeResponses = await Promise.all( + searchResults.map(async r => { + try { + console.log("Loading ", r.id) + return await Wikidata.LoadWikidataEntry(r.id).AsPromise() + } catch (e) { + console.error(e) + return undefined; } - if (wd.claims.get("P31" /*Instance of*/)?.has("Q4167410"/* Wikimedia Disambiguation page*/)) { - return false; - } - return true; - }) - responses.splice(maxCount, responses.length - maxCount) - return responses + })) + return Utils.NoNull(maybeResponses.map(r => r["success"])) } /** * Gets the 'key' segment from a URL - * + * * Wikidata.ExtractKey("https://www.wikidata.org/wiki/Lexeme:L614072") // => "L614072" + * Wikidata.ExtractKey("http://www.wikidata.org/entity/Q55008046") // => "Q55008046" */ public static ExtractKey(value: string | number): string { if (typeof value === "number") { @@ -271,6 +315,35 @@ export default class Wikidata { return undefined; } + /** + * Converts 'Q123' into 123, returns undefined if invalid + * + * Wikidata.QIdToNumber("Q123") // => 123 + * Wikidata.QIdToNumber(" Q123 ") // => 123 + * Wikidata.QIdToNumber(" X123 ") // => undefined + * Wikidata.QIdToNumber(" Q123X ") // => undefined + * Wikidata.QIdToNumber(undefined) // => undefined + * Wikidata.QIdToNumber(123) // => 123 + */ + public static QIdToNumber(q: string | number): number | undefined { + if(q === undefined || q === null){ + return + } + if(typeof q === "number"){ + return q + } + q = q.trim() + if (!q.startsWith("Q")) { + return + } + q = q.substr(1) + const n = Number(q) + if (isNaN(n)) { + return + } + return n + } + public static IdToArticle(id: string) { if (id.startsWith("Q")) { return "https://wikidata.org/wiki/" + id @@ -305,4 +378,4 @@ export default class Wikidata { return WikidataResponse.fromJson(response) } -} \ No newline at end of file +} diff --git a/Models/Constants.ts b/Models/Constants.ts index 431aacf2c..e829a39de 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -2,7 +2,7 @@ import {Utils} from "../Utils"; export default class Constants { - public static vNumber = "0.19.0-alpha"; + public static vNumber = "0.18.2"; public static ImgurApiKey = '7070e7167f0a25a' public static readonly mapillary_client_token_v4 = "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85" diff --git a/Models/ThemeConfig/Conversion/AddContextToTranslations.ts b/Models/ThemeConfig/Conversion/AddContextToTranslations.ts index 9fc3cd1e3..9e3dc8c56 100644 --- a/Models/ThemeConfig/Conversion/AddContextToTranslations.ts +++ b/Models/ThemeConfig/Conversion/AddContextToTranslations.ts @@ -38,16 +38,87 @@ export class AddContextToTranslations extends DesugaringStep { * ] * } * rewritten // => expected + * + * // should use the ID if one is present instead of the index + * const theme = { + * layers: [ + * { + * tagRenderings:[ + * + * {id: "some-tr", + * question:{ + * en:"Question?" + * } + * } + * ] + * } + * ] + * } + * const rewritten = new AddContextToTranslations("prefix:").convert(theme, "context").result + * const expected = { + * layers: [ + * { + * tagRenderings:[ + * + * {id: "some-tr", + * question:{ + * _context: "prefix:context.layers.0.tagRenderings.some-tr.question" + * en:"Question?" + * } + * } + * ] + * } + * ] + * } + * rewritten // => expected + * + * // should preserve nulls + * const theme = { + * layers: [ + * { + * builtin: ["abc"], + * override: { + * name:null + * } + * } + * ] + * } + * const rewritten = new AddContextToTranslations("prefix:").convert(theme, "context").result + * const expected = { + * layers: [ + * { + * builtin: ["abc"], + * override: { + * name: null + * } + * } + * ] + * } + * rewritten // => expected */ convert(json: T, context: string): { result: T; errors?: string[]; warnings?: string[]; information?: string[] } { const result = Utils.WalkJson(json, (leaf, path) => { + if(leaf === undefined || leaf === null){ + return leaf + } if (typeof leaf === "object") { + + // follow the path. If we encounter a number, check that there is no ID we can use instead + let breadcrumb = json; + for (let i = 0; i < path.length; i++) { + const pointer = path[i] + breadcrumb = breadcrumb[pointer] + if(pointer.match("[0-9]+") && breadcrumb["id"] !== undefined){ + path[i] = breadcrumb["id"] + } + } + return {...leaf, _context: this._prefix + context + "." + path.join(".")} } else { return leaf } - }, obj => obj !== undefined && obj !== null && Translations.isProbablyATranslation(obj)) + }, obj => obj === undefined || obj === null || Translations.isProbablyATranslation(obj)) return { result diff --git a/Models/ThemeConfig/Conversion/Conversion.ts b/Models/ThemeConfig/Conversion/Conversion.ts index f947ed916..5b6b72c00 100644 --- a/Models/ThemeConfig/Conversion/Conversion.ts +++ b/Models/ThemeConfig/Conversion/Conversion.ts @@ -158,6 +158,20 @@ export class On extends DesugaringStep { } } +export class Pass extends Conversion { + constructor(message?: string) { + super(message??"Does nothing, often to swap out steps in testing", [], "Pass"); + } + + + convert(json: T, context: string): { result: T; errors?: string[]; warnings?: string[]; information?: string[] } { + return { + result: json + }; + } + +} + export class Concat extends Conversion { private readonly _step: Conversion; @@ -202,13 +216,18 @@ export class Fuse extends DesugaringStep { const information = [] for (let i = 0; i < this.steps.length; i++) { const step = this.steps[i]; - let r = step.convert(json, "While running step " + step.name + ": " + context) - errors.push(...r.errors ?? []) - warnings.push(...r.warnings ?? []) - information.push(...r.information ?? []) - json = r.result - if (errors.length > 0) { - break; + try{ + let r = step.convert(json, "While running step " + step.name + ": " + context) + errors.push(...r.errors ?? []) + warnings.push(...r.warnings ?? []) + information.push(...r.information ?? []) + json = r.result + if (errors.length > 0) { + break; + } + }catch(e){ + console.error("Step "+step.name+" failed due to "+e); + throw e } } return { diff --git a/Models/ThemeConfig/Conversion/PrepareTheme.ts b/Models/ThemeConfig/Conversion/PrepareTheme.ts index d2cf44bca..8a9877e10 100644 --- a/Models/ThemeConfig/Conversion/PrepareTheme.ts +++ b/Models/ThemeConfig/Conversion/PrepareTheme.ts @@ -1,4 +1,4 @@ -import {Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, SetDefault} from "./Conversion"; +import {Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault} from "./Conversion"; import {LayoutConfigJson} from "../Json/LayoutConfigJson"; import {PrepareLayer} from "./PrepareLayer"; import {LayerConfigJson} from "../Json/LayerConfigJson"; @@ -13,28 +13,30 @@ import {AddContextToTranslations} from "./AddContextToTranslations"; class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfigJson[]> { private readonly _state: DesugaringContext; + constructor( state: DesugaringContext, ) { - super("Converts the identifier of a builtin layer into the actual layer, or converts a 'builtin' syntax with override in the fully expanded form", [],"SubstituteLayer"); + super("Converts the identifier of a builtin layer into the actual layer, or converts a 'builtin' syntax with override in the fully expanded form", [], "SubstituteLayer"); this._state = state; } - + convert(json: string | LayerConfigJson, context: string): { result: LayerConfigJson[]; errors: string[], information?: string[] } { const errors = [] const information = [] - const state= this._state - function reportNotFound(name: string){ + const state = this._state + + function reportNotFound(name: string) { const knownLayers = Array.from(state.sharedLayers.keys()) - const withDistance = knownLayers.map(lname => [lname, Utils.levenshteinDistance(name, lname)]) + const withDistance = knownLayers.map(lname => [lname, Utils.levenshteinDistance(name, lname)]) withDistance.sort((a, b) => a[1] - b[1]) const ids = withDistance.map(n => n[0]) - // Known builtin layers are "+.join(",")+"\n For more information, see " + // Known builtin layers are "+.join(",")+"\n For more information, see " errors.push(`${context}: The layer with name ${name} was not found as a builtin layer. Perhaps you meant ${ids[0]}, ${ids[1]} or ${ids[2]}? For an overview of all available layers, refer to https://github.com/pietervdvn/MapComplete/blob/develop/Docs/BuiltinLayers.md`) } - - + + if (typeof json === "string") { const found = state.sharedLayers.get(json) if (found === undefined) { @@ -72,40 +74,40 @@ class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfig } catch (e) { errors.push(`At ${context}: could not apply an override due to: ${e}.\nThe override is: ${JSON.stringify(json["override"],)}`) } - - if(json["hideTagRenderingsWithLabels"]){ + + if (json["hideTagRenderingsWithLabels"]) { const hideLabels: Set = new Set(json["hideTagRenderingsWithLabels"]) // These labels caused at least one deletion - const usedLabels : Set = new Set(); + const usedLabels: Set = new Set(); const filtered = [] for (const tr of found.tagRenderings) { const labels = tr["labels"] - if(labels !== undefined){ + if (labels !== undefined) { const forbiddenLabel = labels.findIndex(l => hideLabels.has(l)) - if(forbiddenLabel >= 0){ + if (forbiddenLabel >= 0) { usedLabels.add(labels[forbiddenLabel]) - information.push(context+": Dropping tagRendering "+tr["id"]+" as it has a forbidden label: "+labels[forbiddenLabel]) + information.push(context + ": Dropping tagRendering " + tr["id"] + " as it has a forbidden label: " + labels[forbiddenLabel]) continue } } - - if(hideLabels.has(tr["id"])){ + + if (hideLabels.has(tr["id"])) { usedLabels.add(tr["id"]) - information.push(context+": Dropping tagRendering "+tr["id"]+" as its id is a forbidden label") + information.push(context + ": Dropping tagRendering " + tr["id"] + " as its id is a forbidden label") continue } - if(hideLabels.has(tr["group"])){ + if (hideLabels.has(tr["group"])) { usedLabels.add(tr["group"]) - information.push(context+": Dropping tagRendering "+tr["id"]+" as its group `"+tr["group"]+"` is a forbidden label") + information.push(context + ": Dropping tagRendering " + tr["id"] + " as its group `" + tr["group"] + "` is a forbidden label") continue } filtered.push(tr) } const unused = Array.from(hideLabels).filter(l => !usedLabels.has(l)) - if(unused.length > 0){ - errors.push("This theme specifies that certain tagrenderings have to be removed based on forbidden layers. One or more of these layers did not match any tagRenderings and caused no deletions: "+unused.join(", ")+"\n This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore") + if (unused.length > 0) { + errors.push("This theme specifies that certain tagrenderings have to be removed based on forbidden layers. One or more of these layers did not match any tagRenderings and caused no deletions: " + unused.join(", ") + "\n This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore") } found.tagRenderings = filtered } @@ -130,7 +132,7 @@ class AddDefaultLayers extends DesugaringStep { private _state: DesugaringContext; constructor(state: DesugaringContext) { - super("Adds the default layers, namely: " + Constants.added_by_default.join(", "), ["layers"],"AddDefaultLayers"); + super("Adds the default layers, namely: " + Constants.added_by_default.join(", "), ["layers"], "AddDefaultLayers"); this._state = state; } @@ -147,8 +149,8 @@ class AddDefaultLayers extends DesugaringStep { errors.push("Default layer " + layerName + " not found") continue } - if(alreadyLoaded.has(v.id)){ - warnings.push("Layout "+context+" already has a layer with name "+v.id+"; skipping inclusion of this builtin layer") + if (alreadyLoaded.has(v.id)) { + warnings.push("Layout " + context + " already has a layer with name " + v.id + "; skipping inclusion of this builtin layer") continue } json.layers.push(v) @@ -165,7 +167,7 @@ class AddDefaultLayers extends DesugaringStep { class AddImportLayers extends DesugaringStep { constructor() { - super("For every layer in the 'layers'-list, create a new layer which'll import notes. (Note that priviliged layers and layers which have a geojson-source set are ignored)", ["layers"],"AddImportLayers"); + super("For every layer in the 'layers'-list, create a new layer which'll import notes. (Note that priviliged layers and layers which have a geojson-source set are ignored)", ["layers"], "AddImportLayers"); } convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[] } { @@ -176,7 +178,7 @@ class AddImportLayers extends DesugaringStep { json.layers = [...json.layers] - if(json.enableNoteImports ?? true) { + if (json.enableNoteImports ?? true) { const creator = new CreateNoteImportLayer() for (let i1 = 0; i1 < allLayers.length; i1++) { const layer = allLayers[i1]; @@ -222,15 +224,16 @@ class AddImportLayers extends DesugaringStep { export class AddMiniMap extends DesugaringStep { private readonly _state: DesugaringContext; - constructor(state: DesugaringContext, ) { - super("Adds a default 'minimap'-element to the tagrenderings if none of the elements define such a minimap", ["tagRenderings"],"AddMiniMap"); + + constructor(state: DesugaringContext,) { + super("Adds a default 'minimap'-element to the tagrenderings if none of the elements define such a minimap", ["tagRenderings"], "AddMiniMap"); this._state = state; } /** * Returns true if this tag rendering has a minimap in some language. * Note: this minimap can be hidden by conditions - * + * * AddMiniMap.hasMinimap({render: "{minimap()}"}) // => true * AddMiniMap.hasMinimap({render: {en: "{minimap()}"}}) // => true * AddMiniMap.hasMinimap({render: {en: "{minimap()}", nl: "{minimap()}"}}) // => true @@ -280,23 +283,23 @@ export class AddMiniMap extends DesugaringStep { } } -class AddContextToTransltionsInLayout extends DesugaringStep { - +class AddContextToTransltionsInLayout extends DesugaringStep { + constructor() { - super("Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too",["_context"], "AddContextToTranlationsInLayout"); + super("Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too", ["_context"], "AddContextToTranlationsInLayout"); } - + convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { const conversion = new AddContextToTranslations("themes:") return conversion.convert(json, json.id); } - + } class ApplyOverrideAll extends DesugaringStep { constructor() { - super("Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards", ["overrideAll", "layers"],"ApplyOverrideAll"); + super("Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards", ["overrideAll", "layers"], "ApplyOverrideAll"); } convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } { @@ -325,8 +328,9 @@ class ApplyOverrideAll extends DesugaringStep { class AddDependencyLayersToTheme extends DesugaringStep { private readonly _state: DesugaringContext; - constructor(state: DesugaringContext, ) { - super("If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)", ["layers"],"AddDependencyLayersToTheme"); + + constructor(state: DesugaringContext,) { + super("If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)", ["layers"], "AddDependencyLayersToTheme"); this._state = state; } @@ -340,17 +344,17 @@ class AddDependencyLayersToTheme extends DesugaringStep { const dependencies: { neededLayer: string, reason: string, context?: string, neededBy: string }[] = [] for (const layerConfig of alreadyLoaded) { - try{ + try { const layerDeps = DependencyCalculator.getLayerDependencies(new LayerConfig(layerConfig)) dependencies.push(...layerDeps) - }catch(e){ + } catch (e) { console.error(e) - throw "Detecting layer dependencies for "+layerConfig.id+" failed due to "+e + throw "Detecting layer dependencies for " + layerConfig.id + " failed due to " + e } } for (const dependency of dependencies) { - if(loadedLayerIds.has(dependency.neededLayer)){ + if (loadedLayerIds.has(dependency.neededLayer)) { // We mark the needed layer as 'mustLoad' alreadyLoaded.find(l => l.id === dependency.neededLayer).forceLoad = true } @@ -380,7 +384,7 @@ class AddDependencyLayersToTheme extends DesugaringStep { } } while (unmetDependencies.length > 0) - + return dependenciesToAdd.map(dep => { dep = Utils.Clone(dep); dep.forceLoad = true @@ -418,46 +422,47 @@ class AddDependencyLayersToTheme extends DesugaringStep { class PreparePersonalTheme extends DesugaringStep { private readonly _state: DesugaringContext; + constructor(state: DesugaringContext) { - super("Adds every public layer to the personal theme",["layers"],"PreparePersonalTheme"); + super("Adds every public layer to the personal theme", ["layers"], "PreparePersonalTheme"); this._state = state; } convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { - if(json.id !== "personal"){ + if (json.id !== "personal") { return {result: json} } - + json.layers = Array.from(this._state.sharedLayers.keys()).filter(l => Constants.priviliged_layers.indexOf(l) < 0) return {result: json}; } - + } -class WarnForUnsubstitutedLayersInTheme extends DesugaringStep{ - +class WarnForUnsubstitutedLayersInTheme extends DesugaringStep { + constructor() { - super("Generates a warning if a theme uses an unsubstituted layer", ["layers"],"WarnForUnsubstitutedLayersInTheme"); + super("Generates a warning if a theme uses an unsubstituted layer", ["layers"], "WarnForUnsubstitutedLayersInTheme"); } - + convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { - if(json.hideFromOverview === true){ + if (json.hideFromOverview === true) { return {result: json} } const warnings = [] for (const layer of json.layers) { - if(typeof layer === "string"){ + if (typeof layer === "string") { continue } - if(layer["builtin"] !== undefined){ + if (layer["builtin"] !== undefined) { continue } - if(layer["source"]["geojson"] !== undefined){ + if (layer["source"]["geojson"] !== undefined) { // We turn a blind eye for import layers continue } - - const wrn = "The theme "+json.id+" has an inline layer: "+layer["id"]+". This is discouraged." + + const wrn = "The theme " + json.id + " has an inline layer: " + layer["id"] + ". This is discouraged." warnings.push(wrn) } return { @@ -465,13 +470,16 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep warnings }; } - + } export class PrepareTheme extends Fuse { - constructor(state: DesugaringContext) { + constructor(state: DesugaringContext, options?: { + skipDefaultLayers: false | boolean + }) { super( "Fully prepares and expands a theme", + new AddContextToTransltionsInLayout(), new PreparePersonalTheme(state), new WarnForUnsubstitutedLayersInTheme(), @@ -483,7 +491,7 @@ export class PrepareTheme extends Fuse { new ApplyOverrideAll(), // And then we prepare all the layers _again_ in case that an override all contained unexpanded tagrenderings! new On("layers", new Each(new PrepareLayer(state))), - new AddDefaultLayers(state), + options?.skipDefaultLayers ? new Pass("AddDefaultLayers is disabled due to the set flag") : new AddDefaultLayers(state), new AddDependencyLayersToTheme(state), new AddImportLayers(), new On("layers", new Each(new AddMiniMap(state))) diff --git a/Models/ThemeConfig/Conversion/Validation.ts b/Models/ThemeConfig/Conversion/Validation.ts index 4bdf9c415..b0c121953 100644 --- a/Models/ThemeConfig/Conversion/Validation.ts +++ b/Models/ThemeConfig/Conversion/Validation.ts @@ -68,7 +68,7 @@ class ValidateTheme extends DesugaringStep { const warnings = [] const information = [] - const theme = new LayoutConfig(json, true, "test") + const theme = new LayoutConfig(json, true) { // Legacy format checks @@ -217,12 +217,17 @@ class MiscThemeChecks extends DesugaringStep{ convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { const warnings = [] + const errors = [] + if(json.id !== "personal" && (json.layers === undefined || json.layers.length === 0)){ + errors.push("The theme "+json.id+" has no 'layers' defined ("+context+")") + } if(json.socialImage === ""){ warnings.push("Social image for theme "+json.id+" is the emtpy string") } return { result :json, - warnings + warnings, + errors }; } } @@ -231,8 +236,8 @@ export class PrevalidateTheme extends Fuse { constructor() { super("Various consistency checks on the raw JSON", - new OverrideShadowingCheck(), - new MiscThemeChecks() + new MiscThemeChecks(), + new OverrideShadowingCheck() ); } diff --git a/Models/ThemeConfig/Json/PointRenderingConfigJson.ts b/Models/ThemeConfig/Json/PointRenderingConfigJson.ts index 5170f8953..c9a4abc9d 100644 --- a/Models/ThemeConfig/Json/PointRenderingConfigJson.ts +++ b/Models/ThemeConfig/Json/PointRenderingConfigJson.ts @@ -13,9 +13,10 @@ export default interface PointRenderingConfigJson { /** * All the locations that this point should be rendered at. - * Using `location: ["point", "centroid"] will always render centerpoint + * Using `location: ["point", "centroid"] will always render centerpoint. + * 'projected_centerpoint' will show an item on the line itself, near the middle of the line. (LineStrings only) */ - location: ("point" | "centroid" | "start" | "end" | string)[] + location: ("point" | "centroid" | "start" | "end" | "projected_centerpoint" | string)[] /** * The icon for an element. diff --git a/Models/ThemeConfig/Json/UnitConfigJson.ts b/Models/ThemeConfig/Json/UnitConfigJson.ts index 5eba5eaf4..bde2683b2 100644 --- a/Models/ThemeConfig/Json/UnitConfigJson.ts +++ b/Models/ThemeConfig/Json/UnitConfigJson.ts @@ -18,9 +18,12 @@ export default interface UnitConfigJson { export interface ApplicableUnitJson { /** - * The canonical value which will be added to the text. + * The canonical value which will be added to the value in OSM. * e.g. "m" for meters - * If the user inputs '42', the canonical value will be added and it'll become '42m' + * If the user inputs '42', the canonical value will be added and it'll become '42m'. + * + * Important: often, _no_ canonical values are expected, e.g. in the case of 'maxspeed' where 'km/h' is the default. + * In this case, an empty string should be used */ canonicalDenomination: string, /** diff --git a/Models/ThemeConfig/LayerConfig.ts b/Models/ThemeConfig/LayerConfig.ts index ce2e56f05..ade6d6b6d 100644 --- a/Models/ThemeConfig/LayerConfig.ts +++ b/Models/ThemeConfig/LayerConfig.ts @@ -127,12 +127,16 @@ export default class LayerConfig extends WithContextLoader { idKey: json.source["idKey"] }, + Constants.priviliged_layers.indexOf(this.id) > 0, json.id ); this.allowSplit = json.allowSplit ?? false; this.name = Translations.T(json.name, translationContext + ".name"); + if(json.units!==undefined && !Array.isArray(json.units)){ + throw "At "+context+".units: the 'units'-section should be a list; you probably have an object there" + } this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`))) if (json.description !== undefined) { diff --git a/Models/ThemeConfig/LayoutConfig.ts b/Models/ThemeConfig/LayoutConfig.ts index 402f28892..2d8598f6a 100644 --- a/Models/ThemeConfig/LayoutConfig.ts +++ b/Models/ThemeConfig/LayoutConfig.ts @@ -56,9 +56,17 @@ export default class LayoutConfig { public readonly usedImages: string[] public readonly extraLink?: ExtraLinkConfig - constructor(json: LayoutConfigJson, official = true, context?: string) { + public readonly definedAtUrl? : string; + public readonly definitionRaw?: string; + + constructor(json: LayoutConfigJson, official = true,options?: { + definedAtUrl?: string, + definitionRaw?: string + }) { this.official = official; this.id = json.id; + this.definedAtUrl = options?.definedAtUrl + this.definitionRaw = options?.definitionRaw if (official) { if (json.id.toLowerCase() !== json.id) { throw "The id of a theme should be lowercase: " + json.id @@ -67,11 +75,7 @@ export default class LayoutConfig { throw "The id of a theme should match [a-z0-9-_]*: " + json.id } } - if(context === undefined){ - context = this.id - }else{ - context = context + "." + this.id; - } + const context = this.id this.maintainer = json.maintainer; this.credits = json.credits; this.version = json.version; diff --git a/Models/ThemeConfig/PointRenderingConfig.ts b/Models/ThemeConfig/PointRenderingConfig.ts index 0a02149b8..39dcec156 100644 --- a/Models/ThemeConfig/PointRenderingConfig.ts +++ b/Models/ThemeConfig/PointRenderingConfig.ts @@ -15,8 +15,8 @@ import {VariableUiElement} from "../../UI/Base/VariableUIElement"; export default class PointRenderingConfig extends WithContextLoader { - private static readonly allowed_location_codes = new Set(["point", "centroid", "start", "end"]) - public readonly location: Set<"point" | "centroid" | "start" | "end" | string> + private static readonly allowed_location_codes = new Set(["point", "centroid", "start", "end","projected_centerpoint"]) + public readonly location: Set<"point" | "centroid" | "start" | "end" | "projected_centerpoint" | string> public readonly icon: TagRenderingConfig; public readonly iconBadges: { if: TagsFilter; then: TagRenderingConfig }[]; diff --git a/Models/ThemeConfig/SourceConfig.ts b/Models/ThemeConfig/SourceConfig.ts index 0edd9b7b2..5c31bdbcf 100644 --- a/Models/ThemeConfig/SourceConfig.ts +++ b/Models/ThemeConfig/SourceConfig.ts @@ -1,5 +1,6 @@ import {TagsFilter} from "../../Logic/Tags/TagsFilter"; import {RegexTag} from "../../Logic/Tags/RegexTag"; +import {param} from "jquery"; export default class SourceConfig { @@ -19,7 +20,7 @@ export default class SourceConfig { isOsmCache?: boolean, geojsonSourceLevel?: number, idKey?: string - }, context?: string) { + }, isSpecialLayer: boolean, context?: string) { let defined = 0; if (params.osmTags) { @@ -43,6 +44,15 @@ export default class SourceConfig { throw `Source defines a geojson-zoomLevel, but does not specify {x} nor {y} (or equivalent), this is probably a bug (in context ${context})` } } + if(params.osmTags !== undefined && !isSpecialLayer){ + const optimized = params.osmTags.optimize() + if(optimized === false){ + throw "Error at "+context+": the specified tags are conflicting with each other: they will never match anything at all" + } + if(optimized === true){ + throw "Error at "+context+": the specified tags are very wide: they will always match everything" + } + } this.osmTags = params.osmTags ?? new RegexTag("id", /.*/); this.overpassScript = params.overpassScript; this.geojsonSource = params.geojsonSource; diff --git a/Models/ThemeConfig/TagRenderingConfig.ts b/Models/ThemeConfig/TagRenderingConfig.ts index 0f2aa3fdb..aa9f05eb8 100644 --- a/Models/ThemeConfig/TagRenderingConfig.ts +++ b/Models/ThemeConfig/TagRenderingConfig.ts @@ -1,4 +1,4 @@ -import {Translation} from "../../UI/i18n/Translation"; +import {Translation, TypedTranslation} from "../../UI/i18n/Translation"; import {TagsFilter} from "../../Logic/Tags/TagsFilter"; import Translations from "../../UI/i18n/Translations"; import {TagUtils} from "../../Logic/Tags/TagUtils"; @@ -22,8 +22,8 @@ export default class TagRenderingConfig { public readonly id: string; public readonly group: string; - public readonly render?: Translation; - public readonly question?: Translation; + public readonly render?: TypedTranslation; + public readonly question?: TypedTranslation; public readonly condition?: TagsFilter; public readonly configuration_warnings: string[] = [] @@ -43,7 +43,7 @@ export default class TagRenderingConfig { public readonly mappings?: { readonly if: TagsFilter, readonly ifnot?: TagsFilter, - readonly then: Translation, + readonly then: TypedTranslation, readonly icon: string, readonly iconClass: string readonly hideInAnswer: boolean | TagsFilter @@ -110,12 +110,13 @@ export default class TagRenderingConfig { } const type = json.freeform.type ?? "string" - let placeholder = Translations.T(json.freeform.placeholder) + let placeholder: Translation = Translations.T(json.freeform.placeholder) if (placeholder === undefined) { const typeDescription = Translations.t.validation[type]?.description - placeholder = Translations.T(json.freeform.key+" ("+type+")") if(typeDescription !== undefined){ - placeholder = placeholder.Subs({[type]: typeDescription}) + placeholder = Translations.T(json.freeform.key+" ("+type+")").Subs({[type]: typeDescription}) + }else{ + placeholder = Translations.T(json.freeform.key+" ("+type+")") } } @@ -383,7 +384,7 @@ export default class TagRenderingConfig { let freeformKeyDefined = this.freeform?.key !== undefined; let usedFreeformValues = new Set() // We run over all the mappings first, to check if the mapping matches - const applicableMappings: { then: Translation, img?: string }[] = Utils.NoNull((this.mappings ?? [])?.map(mapping => { + const applicableMappings: { then: TypedTranslation, img?: string }[] = Utils.NoNull((this.mappings ?? [])?.map(mapping => { if (mapping.if === undefined) { return mapping; } @@ -404,7 +405,7 @@ export default class TagRenderingConfig { const leftovers = freeformValues.filter(v => !usedFreeformValues.has(v)) for (const leftover of leftovers) { applicableMappings.push({then: - this.render.replace("{"+this.freeform.key+"}", leftover) + new TypedTranslation(this.render.replace("{"+this.freeform.key+"}", leftover).translations) }) } } @@ -412,7 +413,7 @@ export default class TagRenderingConfig { return applicableMappings } - public GetRenderValue(tags: any, defltValue: any = undefined): Translation { + public GetRenderValue(tags: any, defltValue: any = undefined): TypedTranslation { return this.GetRenderValueWithImage(tags, defltValue).then } @@ -421,7 +422,7 @@ export default class TagRenderingConfig { * Not compatible with multiAnswer - use GetRenderValueS instead in that case * @constructor */ - public GetRenderValueWithImage(tags: any, defltValue: any = undefined): { then: Translation, icon?: string } { + public GetRenderValueWithImage(tags: any, defltValue: any = undefined): { then: TypedTranslation, icon?: string } { if (this.mappings !== undefined && !this.multiAnswer) { for (const mapping of this.mappings) { if (mapping.if === undefined) { diff --git a/UI/Base/LinkToWeblate.ts b/UI/Base/LinkToWeblate.ts index d088658ab..1239409a2 100644 --- a/UI/Base/LinkToWeblate.ts +++ b/UI/Base/LinkToWeblate.ts @@ -4,6 +4,7 @@ import Link from "./Link"; import Svg from "../../Svg"; export default class LinkToWeblate extends VariableUiElement { + private static URI: any; constructor(context: string, availableTranslations: object) { super( Locale.language.map(ln => { if (Locale.showLinkToWeblate.data === false) { @@ -36,4 +37,10 @@ export default class LinkToWeblate extends VariableUiElement { const baseUrl = "https://hosted.weblate.org/translate/mapcomplete/" return baseUrl + category + "/" + language + "/?offset=1&q=context%3A%3D%22" + key + "%22" } + + public static hrefToWeblateZen(language: string, category: string, searchKey: string): string{ + const baseUrl = "https://hosted.weblate.org/zen/mapcomplete/" + // ?offset=1&q=+state%3A%3Ctranslated+context%3Acampersite&sort_by=-priority%2Cposition&checksum= + return baseUrl + category + "/" + language + "?offset=1&q=+state%3A%3Ctranslated+context%3A"+encodeURIComponent(searchKey)+"&sort_by=-priority%2Cposition&checksum=" + } } \ No newline at end of file diff --git a/UI/BaseUIElement.ts b/UI/BaseUIElement.ts index 2157fb2f1..d01b72867 100644 --- a/UI/BaseUIElement.ts +++ b/UI/BaseUIElement.ts @@ -49,7 +49,7 @@ export default abstract class BaseUIElement { */ public SetClass(clss: string) { if (clss == undefined) { - return + return this } const all = clss.split(" ").map(clsName => clsName.trim()); let recordedChange = false; diff --git a/UI/BigComponents/AddNewMarker.ts b/UI/BigComponents/AddNewMarker.ts index 9bd89e3f5..479098bea 100644 --- a/UI/BigComponents/AddNewMarker.ts +++ b/UI/BigComponents/AddNewMarker.ts @@ -14,7 +14,7 @@ export default class AddNewMarker extends Combine { let last = undefined; for (const filteredLayer of filteredLayers) { const layer = filteredLayer.layerDef; - if(layer.name === undefined){ + if(layer.name === undefined && !filteredLayer.isDisplayed.data){ continue } for (const preset of filteredLayer.layerDef.presets) { diff --git a/UI/BigComponents/CopyrightPanel.ts b/UI/BigComponents/CopyrightPanel.ts index c1cadcf8b..1b196f02b 100644 --- a/UI/BigComponents/CopyrightPanel.ts +++ b/UI/BigComponents/CopyrightPanel.ts @@ -22,7 +22,7 @@ import {OsmConnection} from "../../Logic/Osm/OsmConnection"; import Constants from "../../Models/Constants"; import ContributorCount from "../../Logic/ContributorCount"; import Img from "../Base/Img"; -import {Translation} from "../i18n/Translation"; +import {TypedTranslation} from "../i18n/Translation"; import TranslatorsPanel from "./TranslatorsPanel"; export class OpenIdEditor extends VariableUiElement { @@ -198,7 +198,7 @@ export default class CopyrightPanel extends Combine { this.SetStyle("max-width:100%; width: 40rem; margin-left: 0.75rem; margin-right: 0.5rem") } - private static CodeContributors(contributors, translation: Translation): BaseUIElement { + private static CodeContributors(contributors, translation: TypedTranslation<{contributors, hiddenCount}>): BaseUIElement { const total = contributors.contributors.length; let filtered = [...contributors.contributors] diff --git a/UI/BigComponents/LicensePicker.ts b/UI/BigComponents/LicensePicker.ts index 19c608141..619aad54a 100644 --- a/UI/BigComponents/LicensePicker.ts +++ b/UI/BigComponents/LicensePicker.ts @@ -17,7 +17,10 @@ export default class LicensePicker extends DropDown { {value: LicensePicker.ccbysa, shown: Translations.t.image.ccbs.Clone()}, {value: LicensePicker.ccby, shown: Translations.t.image.ccb.Clone()} ], - state?.osmConnection?.GetPreference("pictures-license") ?? new UIEventSource("CC0") + state?.osmConnection?.GetPreference("pictures-license") ?? new UIEventSource("CC0"), + { + select_class:"w-min bg-indigo-100 p-1 rounded hover:bg-indigo-200" + } ) this.SetClass("flex flex-col sm:flex-row").SetStyle("float:left"); } diff --git a/UI/BigComponents/MoreScreen.ts b/UI/BigComponents/MoreScreen.ts index 4fa8d418a..d53a5b9a2 100644 --- a/UI/BigComponents/MoreScreen.ts +++ b/UI/BigComponents/MoreScreen.ts @@ -90,10 +90,10 @@ export default class MoreScreen extends Combine { } let hash = "" - if(layout.definition !== undefined){ - hash = "#"+btoa(JSON.stringify(layout.definition)) + if (layout.definition !== undefined) { + hash = "#" + btoa(JSON.stringify(layout.definition)) } - + const linkText = currentLocation?.map(currentLocation => { const params = [ ["z", currentLocation?.zoom], @@ -106,11 +106,10 @@ export default class MoreScreen extends Combine { }) ?? new UIEventSource(`${linkPrefix}`) - return new SubtleButton(layout.icon, new Combine([ `
`, - new Translation(layout.title, !isCustom && !layout.mustHaveLanguage ? "themes:"+layout.id+".title" : undefined), + new Translation(layout.title, !isCustom && !layout.mustHaveLanguage ? "themes:" + layout.id + ".title" : undefined), `
`, `
`, new Translation(layout.shortDescription)?.SetClass("subtle") ?? "", @@ -128,15 +127,13 @@ export default class MoreScreen extends Combine { } private static createUnofficialButtonFor(state: UserRelatedState, id: string): BaseUIElement { - const allPreferences = state.osmConnection.preferencesHandler.preferences.data; - const length = Number(allPreferences[id + "-length"]) - let str = ""; - for (let i = 0; i < length; i++) { - str += allPreferences[id + "-" + i] - } - if(str === undefined || str === "undefined"){ + const pref = state.osmConnection.GetLongPreference(id) + const str = pref.data + if (str === undefined || str === "undefined" || str === "") { + pref.setData(null) return undefined } + try { const value: { id: string @@ -149,7 +146,8 @@ export default class MoreScreen extends Combine { value.isOfficial = false return MoreScreen.createLinkButton(state, value, true) } catch (e) { - console.debug("Could not parse unofficial theme information for " + id, "The json is: ", str, e) + console.warn("Removing theme " + id + " as it could not be parsed from the preferences") + pref.setData(null) return undefined } } @@ -163,16 +161,14 @@ export default class MoreScreen extends Combine { for (const key in allPreferences) { if (key.startsWith(prefix) && key.endsWith("-combined-length")) { - const id = key.substring(0, key.length - "-length".length) + const id = key.substring("mapcomplete-".length, key.length - "-combined-length".length) ids.push(id) } } - return ids }); var stableIds = UIEventSource.ListStabilized(currentIds) - return new VariableUiElement( stableIds.map(ids => { const allThemes: BaseUIElement[] = [] @@ -182,12 +178,11 @@ export default class MoreScreen extends Combine { allThemes.push(link.SetClass(buttonClass)) } } - if (allThemes.length <= 0) { return undefined; } return new Combine([ - Translations.t.general.customThemeIntro.Clone(), + Translations.t.general.customThemeIntro, new Combine(allThemes).SetClass(themeListClasses) ]); })); diff --git a/UI/BigComponents/ShareScreen.ts b/UI/BigComponents/ShareScreen.ts index a55062779..de96839bf 100644 --- a/UI/BigComponents/ShareScreen.ts +++ b/UI/BigComponents/ShareScreen.ts @@ -14,6 +14,8 @@ import BaseLayer from "../../Models/BaseLayer"; import FilteredLayer from "../../Models/FilteredLayer"; import {InputElement} from "../Input/InputElement"; import CheckBoxes, {CheckBox} from "../Input/Checkboxes"; +import {SubtleButton} from "../Base/SubtleButton"; +import LZString from "lz-string"; export default class ShareScreen extends Combine { @@ -24,14 +26,6 @@ export default class ShareScreen extends Combine { const optionCheckboxes: InputElement[] = [] const optionParts: (UIEventSource)[] = []; - function check() { - return Svg.checkmark_svg().SetStyle("width: 1.5em; display:inline-block;"); - } - - function nocheck() { - return Svg.no_checkmark_svg().SetStyle("width: 1.5em; display: inline-block;"); - } - const includeLocation = new CheckBox(tr.fsIncludeCurrentLocation, true) optionCheckboxes.push(includeLocation); @@ -49,6 +43,7 @@ export default class ShareScreen extends Combine { } else { return null; } + }, [currentLocation])); @@ -119,6 +114,9 @@ export default class ShareScreen extends Combine { } + if(layout.definitionRaw !== undefined){ + optionParts.push(new UIEventSource("userlayout="+(layout.definedAtUrl ?? layout.id))) + } const options = new Combine(optionCheckboxes).SetClass("flex flex-col") const url = (currentLocation ?? new UIEventSource(undefined)).map(() => { @@ -126,13 +124,21 @@ export default class ShareScreen extends Combine { const host = window.location.host; let path = window.location.pathname; path = path.substr(0, path.lastIndexOf("/")); - let literalText = `https://${host}${path}/${layout.id.toLowerCase()}` + let id = layout.id.toLowerCase() + if(layout.definitionRaw !== undefined){ + id="theme.html" + } + let literalText = `https://${host}${path}/${id}` + let hash = "" + if(layout.definedAtUrl === undefined && layout.definitionRaw !== undefined){ + hash = "#"+ LZString.compressToBase64( Utils.MinifyJSON(layout.definitionRaw)) + } const parts = Utils.NoEmpty(Utils.NoNull(optionParts.map((eventSource) => eventSource.data))); if (parts.length === 0) { - return literalText; + return literalText + hash; } - return literalText + "?" + parts.join("&"); + return literalText + "?" + parts.join("&") + hash; }, optionParts); @@ -184,13 +190,27 @@ export default class ShareScreen extends Combine { }); + + let downloadThemeConfig: BaseUIElement = undefined; + if(layout.definitionRaw !== undefined){ + downloadThemeConfig = new SubtleButton(Svg.download_svg(), new Combine([ + tr.downloadCustomTheme, + tr.downloadCustomThemeHelp.SetClass("subtle") + ]).onClick(() => { + Utils.offerContentsAsDownloadableFile(layout.definitionRaw, layout.id+".mapcomplete-theme-definition.json", { + mimetype:"application/json" + }) + }) + .SetClass("flex flex-col")) + } super([ - tr.intro.Clone(), + tr.intro, link, new VariableUiElement(linkStatus), - tr.addToHomeScreen.Clone(), - tr.embedIntro.Clone(), + downloadThemeConfig, + tr.addToHomeScreen, + tr.embedIntro, options, iframeCode, ]) diff --git a/UI/BigComponents/SimpleAddUI.ts b/UI/BigComponents/SimpleAddUI.ts index 2e8371a0a..931092863 100644 --- a/UI/BigComponents/SimpleAddUI.ts +++ b/UI/BigComponents/SimpleAddUI.ts @@ -191,7 +191,7 @@ export default class SimpleAddUI extends Toggle { preset.icon(), new Combine([ title.SetClass("font-bold"), - Translations.WT(preset.description)?.FirstSentence() + preset.description?.FirstSentence() ]).SetClass("flex flex-col") ) } @@ -208,15 +208,20 @@ export default class SimpleAddUI extends Toggle { const allButtons = []; for (const layer of state.filteredLayers.data) { - if (layer.isDisplayed.data === false && !state.featureSwitchFilter.data) { - // The layer is not displayed and we cannot enable the layer control -> we skip - continue; + if (layer.isDisplayed.data === false) { + // The layer is not displayed... + if(!state.featureSwitchFilter.data){ + // ...and we cannot enable the layer control -> we skip, as these presets can never be shown anyway + continue; + } + + if (layer.layerDef.name === undefined) { + // this layer can never be toggled on in any case, so we skip the presets + continue; + } } - if (layer.layerDef.name === undefined) { - // this is a parlty hidden layer - continue; - } + const presets = layer.layerDef.presets; for (const preset of presets) { diff --git a/UI/BigComponents/TranslatorsPanel.ts b/UI/BigComponents/TranslatorsPanel.ts index a036a1d54..37e80eadb 100644 --- a/UI/BigComponents/TranslatorsPanel.ts +++ b/UI/BigComponents/TranslatorsPanel.ts @@ -14,7 +14,9 @@ import Title from "../Base/Title"; import {UIEventSource} from "../../Logic/UIEventSource"; import {SubtleButton} from "../Base/SubtleButton"; import Svg from "../../Svg"; - +import * as native_languages from "../../assets/language_native.json" +import * as used_languages from "../../assets/generated/used_languages.json" +import BaseUIElement from "../BaseUIElement"; class TranslatorsPanelContent extends Combine { constructor(layout: LayoutConfig, isTranslator: UIEventSource) { @@ -24,36 +26,53 @@ class TranslatorsPanelContent extends Combine { const seed = t.completeness for (const ln of Array.from(completeness.keys())) { - if(ln === "*"){ + if (ln === "*") { continue } if (seed.translations[ln] === undefined) { seed.translations[ln] = seed.translations["en"] } } - + const completenessTr = {} const completenessPercentage = {} seed.SupportedLanguages().forEach(ln => { - completenessTr[ln] = ""+(completeness.get(ln) ?? 0) - completenessPercentage[ln] = ""+Math.round(100 * (completeness.get(ln) ?? 0) / total) + completenessTr[ln] = "" + (completeness.get(ln) ?? 0) + completenessPercentage[ln] = "" + Math.round(100 * (completeness.get(ln) ?? 0) / total) }) - const missingTranslationsFor = (ln: string) => Utils.NoNull(untranslated.get(ln) ?? []) - .filter(ctx => ctx.indexOf(":") >= 0) - .map(ctx => ctx.replace(/note_import_[a-zA-Z0-9_]*/, "note_import")) - .map(context => new Link(context, LinkToWeblate.hrefToWeblate(ln, context), true)) + function missingTranslationsFor(language: string): BaseUIElement[] { + // e.g. "themes:.layers.0.tagRenderings..., or "layers:.description + const missingKeys = Utils.NoNull(untranslated.get(language) ?? []) + .filter(ctx => ctx.indexOf(":") >= 0) + .map(ctx => ctx.replace(/note_import_[a-zA-Z0-9_]*/, "note_import")) + + const hasMissingTheme = missingKeys.some(k => k.startsWith("themes:")) + const missingLayers = Utils.Dedup( missingKeys.filter(k => k.startsWith("layers:")) + .map(k => k.slice("layers:".length).split(".")[0])) + + console.log("Getting untranslated string for",language,"raw:",missingKeys,"hasMissingTheme:",hasMissingTheme,"missingLayers:",missingLayers) + return [ + hasMissingTheme ? new Link("themes:" + layout.id + ".* (zen mode)", LinkToWeblate.hrefToWeblateZen(language, "themes", layout.id), true) : undefined, + ...missingLayers.map(id => new Link("layer:" + id + ".* (zen mode)", LinkToWeblate.hrefToWeblateZen(language, "layers", id), true)), + ...missingKeys.map(context => new Link(context, LinkToWeblate.hrefToWeblate(language, context), true)) + ] + } + // + // // "translationCompleteness": "Translations for {theme} in {language} are at {percentage}: {translated} out of {total}", - const translated = seed.Subs({total, theme: layout.title, + const translated = seed.Subs({ + total, theme: layout.title, percentage: new Translation(completenessPercentage), - translated: new Translation(completenessTr) + translated: new Translation(completenessTr), + language: seed.OnEveryLanguage((_, lng) => native_languages[lng] ?? lng) }) - + super([ new Title( - Translations.t.translations.activateButton, + Translations.t.translations.activateButton, ), new Toggle(t.isTranslator.SetClass("thanks block"), undefined, isTranslator), t.help, @@ -63,15 +82,18 @@ class TranslatorsPanelContent extends Combine { .onClick(() => { Locale.showLinkToWeblate.setData(false) }), - - new VariableUiElement(Locale.language.map(ln => { + new VariableUiElement(Locale.language.map(ln => { const missing = missingTranslationsFor(ln) if (missing.length === 0) { return undefined } + let title = Translations.t.translations.allMissing; + if(untranslated.get(ln) !== undefined){ + title = Translations.t.translations.missing.Subs({count: untranslated.get(ln).length}) + } return new Toggleable( - new Title(Translations.t.translations.missing.Subs({count: missing.length})), + new Title(title), new Combine(missing).SetClass("flex flex-col") ) })) @@ -83,38 +105,37 @@ class TranslatorsPanelContent extends Combine { export default class TranslatorsPanel extends Toggle { - + constructor(state: { layoutToUse: LayoutConfig, isTranslator: UIEventSource }, iconStyle?: string) { const t = Translations.t.translations super( - new Lazy(() => new TranslatorsPanelContent(state.layoutToUse, state.isTranslator) + new Lazy(() => new TranslatorsPanelContent(state.layoutToUse, state.isTranslator) ).SetClass("flex flex-col"), new SubtleButton(Svg.translate_ui().SetStyle(iconStyle), t.activateButton).onClick(() => Locale.showLinkToWeblate.setData(true)), - Locale.showLinkToWeblate + Locale.showLinkToWeblate ) this.SetClass("hidden-on-mobile") - + } - public static MissingTranslationsFor(layout: LayoutConfig) : {completeness: Map, untranslated: Map, total: number} { + public static MissingTranslationsFor(layout: LayoutConfig): { completeness: Map, untranslated: Map, total: number } { let total = 0 const completeness = new Map() const untranslated = new Map() + Utils.WalkObject(layout, (o, path) => { const translation = o; - if(translation.translations["*"] !== undefined){ + if (translation.translations["*"] !== undefined) { return } - if(translation.context === undefined || translation.context.indexOf(":") < 0){ + if (translation.context === undefined || translation.context.indexOf(":") < 0) { // no source given - lets ignore return } - - for (const lang of translation.SupportedLanguages()) { - completeness.set(lang, 1 + (completeness.get(lang) ?? 0)) - } - layout.title.SupportedLanguages().forEach(ln => { + + total ++ + used_languages.languages.forEach(ln => { const trans = translation.translations if (trans["*"] !== undefined) { return; @@ -124,11 +145,11 @@ export default class TranslatorsPanel extends Toggle { untranslated.set(ln, []) } untranslated.get(ln).push(translation.context) + }else{ + completeness.set(ln, 1 + (completeness.get(ln) ?? 0)) } }) - if(translation.translations["*"] === undefined){ - total++ - } + }, o => { if (o === undefined || o === null) { return false; diff --git a/UI/Image/ImageUploadFlow.ts b/UI/Image/ImageUploadFlow.ts index 743b1b2c2..47e775289 100644 --- a/UI/Image/ImageUploadFlow.ts +++ b/UI/Image/ImageUploadFlow.ts @@ -15,6 +15,7 @@ import {VariableUiElement} from "../Base/VariableUIElement"; import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import {OsmConnection} from "../../Logic/Osm/OsmConnection"; import {Changes} from "../../Logic/Osm/Changes"; +import Loading from "../Base/Loading"; export class ImageUploadFlow extends Toggle { @@ -138,16 +139,16 @@ export class ImageUploadFlow extends Toggle { if (l == 0) { return undefined } - return t.uploadFailed.Clone().SetClass("alert"); + return new Loading(t.uploadFailed).SetClass("alert"); })), new VariableUiElement(uploadedCount.map(l => { if (l == 0) { return undefined; } if (l == 1) { - return t.uploadDone.Clone().SetClass("thanks"); + return t.uploadDone.Clone().SetClass("thanks block"); } - return t.uploadMultipleDone.Subs({count: l}).SetClass("thanks") + return t.uploadMultipleDone.Subs({count: l}).SetClass("thanks block") })), fileSelector, diff --git a/UI/ImportFlow/AskMetadata.ts b/UI/ImportFlow/AskMetadata.ts index 9f7c16caf..125b43ed3 100644 --- a/UI/ImportFlow/AskMetadata.ts +++ b/UI/ImportFlow/AskMetadata.ts @@ -4,8 +4,12 @@ import {UIEventSource} from "../../Logic/UIEventSource"; import ValidatedTextField from "../Input/ValidatedTextField"; import {LocalStorageSource} from "../../Logic/Web/LocalStorageSource"; import Title from "../Base/Title"; -import {FixedUiElement} from "../Base/FixedUiElement"; import {VariableUiElement} from "../Base/VariableUIElement"; +import Translations from "../i18n/Translations"; +import {FixedUiElement} from "../Base/FixedUiElement"; +import {SubtleButton} from "../Base/SubtleButton"; +import Svg from "../../Svg"; +import {Utils} from "../../Utils"; export class AskMetadata extends Combine implements FlowStep<{ features: any[], @@ -25,7 +29,7 @@ export class AskMetadata extends Combine implements FlowStep<{ public readonly IsValid: UIEventSource; constructor(params: ({ features: any[], theme: string })) { - + const t = Translations.t.importHelper.askMetadata const introduction = ValidatedTextField.ForType("text").ConstructInputElement({ value: LocalStorageSource.Get("import-helper-introduction-text"), inputStyle: "width: 100%" @@ -42,28 +46,39 @@ export class AskMetadata extends Combine implements FlowStep<{ }) super([ - new Title("Set metadata"), - "Before adding " + params.features.length + " notes, please provide some extra information.", - "Please, write an introduction for someone who sees the note", + new Title(t.title), + t.intro.Subs({count: params.features.length}), + t.giveDescription, introduction.SetClass("w-full border border-black"), - "What is the source of this data? If 'source' is set in the feature, this value will be ignored", - source.SetClass("w-full border border-black"), - "On what wikipage can one find more information about this import?", + t.giveSource, + source.SetClass("w-full border border-black"), + t.giveWikilink , wikilink.SetClass("w-full border border-black"), new VariableUiElement(wikilink.GetValue().map(wikilink => { try{ const url = new URL(wikilink) if(url.hostname.toLowerCase() !== "wiki.openstreetmap.org"){ - return new FixedUiElement("Expected a link to wiki.openstreetmap.org").SetClass("alert"); + return t.shouldBeOsmWikilink.SetClass("alert"); } if(url.pathname.toLowerCase() === "/wiki/main_page"){ - return new FixedUiElement("Nope, the home page isn't allowed either. Enter the URL of a proper wikipage documenting your import").SetClass("alert"); + return t.shouldNotBeHomepage.SetClass("alert"); } }catch(e){ - return new FixedUiElement("Not a valid URL").SetClass("alert") + return t.shouldBeUrl.SetClass("alert") } - })) + })), + t.orDownload, + new SubtleButton(Svg.download_svg(), t.downloadGeojson).OnClickWithLoading("Preparing your download", + async ( ) => { + const geojson = { + type:"FeatureCollection", + features: params.features + } + Utils.offerContentsAsDownloadableFile(JSON.stringify(geojson), "prepared_import_"+params.theme+".geojson",{ + mimetype: "application/vnd.geo+json" + }) + }) ]); this.SetClass("flex flex-col") diff --git a/UI/ImportFlow/CompareToAlreadyExistingNotes.ts b/UI/ImportFlow/CompareToAlreadyExistingNotes.ts index 868504cde..eb0d40f71 100644 --- a/UI/ImportFlow/CompareToAlreadyExistingNotes.ts +++ b/UI/ImportFlow/CompareToAlreadyExistingNotes.ts @@ -21,6 +21,7 @@ import {FixedUiElement} from "../Base/FixedUiElement"; import {VariableUiElement} from "../Base/VariableUIElement"; import * as known_layers from "../../assets/generated/known_layers.json" import {LayerConfigJson} from "../../Models/ThemeConfig/Json/LayerConfigJson"; +import Translations from "../i18n/Translations"; /** * Filters out points for which the import-note already exists, to prevent duplicates @@ -28,11 +29,11 @@ import {LayerConfigJson} from "../../Models/ThemeConfig/Json/LayerConfigJson"; export class CompareToAlreadyExistingNotes extends Combine implements FlowStep<{ bbox: BBox, layer: LayerConfig, features: any[], theme: string }> { public IsValid: UIEventSource - public Value: UIEventSource<{ bbox: BBox, layer: LayerConfig, features: any[] , theme: string}> + public Value: UIEventSource<{ bbox: BBox, layer: LayerConfig, features: any[], theme: string }> - constructor(state, params: { bbox: BBox, layer: LayerConfig, features: any[], theme: string }) { - + constructor(state, params: { bbox: BBox, layer: LayerConfig, features: any[], theme: string }) { + const t = Translations.t.importHelper.compareToAlreadyExistingNotes const layerConfig = known_layers.layers.filter(l => l.id === params.layer.id)[0] if (layerConfig === undefined) { console.error("WEIRD: layer not found in the builtin layer overview") @@ -45,7 +46,7 @@ export class CompareToAlreadyExistingNotes extends Combine implements FlowStep<{ layerDef: importLayer } const allNotesWithinBbox = new GeoJsonSource(flayer, params.bbox.padAbsolute(0.0001)) - + allNotesWithinBbox.features.map(f => MetaTagging.addMetatags( f, { @@ -63,7 +64,6 @@ export class CompareToAlreadyExistingNotes extends Combine implements FlowStep<{ ) ) const alreadyOpenImportNotes = new FilteringFeatureSource(state, undefined, allNotesWithinBbox) - alreadyOpenImportNotes.features.addCallbackD(features => console.log("Loaded and filtered features are", features)) const map = Minimap.createMiniMap() map.SetClass("w-full").SetStyle("height: 500px") @@ -99,43 +99,46 @@ export class CompareToAlreadyExistingNotes extends Combine implements FlowStep<{ }) super([ - new Title("Compare with already existing 'to-import'-notes"), + new Title(t.titleLong), new VariableUiElement( alreadyOpenImportNotes.features.map(notesWithImport => { - if(allNotesWithinBbox.state.data !== undefined && allNotesWithinBbox.state.data["error"] !== undefined){ - return new FixedUiElement("Loading notes failed: "+allNotesWithinBbox.state.data["error"] ) + if (allNotesWithinBbox.state.data !== undefined && allNotesWithinBbox.state.data["error"] !== undefined) { + t.loadingFailed.Subs(allNotesWithinBbox.state.data) } if (allNotesWithinBbox.features.data === undefined || allNotesWithinBbox.features.data.length === 0) { - return new Loading("Fetching notes from OSM") + return new Loading(t.loading) } if (notesWithImport.length === 0) { - return new FixedUiElement("No previous import notes found").SetClass("thanks") + return t.noPreviousNotesFound.SetClass("thanks") } return new Combine([ - "The red elements on the next map are all the data points from your dataset. There are "+params.features.length+" elements in your dataset.", + t.mapExplanation.Subs(params.features), map, - - new VariableUiElement( partitionedImportPoints.map(({noNearby, hasNearby}) => { - - if(noNearby.length === 0){ - // Nothing can be imported - return new FixedUiElement("All of the proposed points have (or had) an import note already").SetClass("alert w-full block").SetStyle("padding: 0.5rem") - } - - if(hasNearby.length === 0){ - // All points can be imported - return new FixedUiElement("All of the proposed points have don't have a previous import note nearby").SetClass("thanks w-full block").SetStyle("padding: 0.5rem") - } - - return new Combine([ - new FixedUiElement(hasNearby.length+" points do have an already existing import note within "+maxDistance.data+" meter.").SetClass("alert"), - "These data points will not be imported and are shown as red dots on the map below", - comparisonMap.SetClass("w-full") - ]).SetClass("w-full") + new VariableUiElement(partitionedImportPoints.map(({noNearby, hasNearby}) => { + + if (noNearby.length === 0) { + // Nothing can be imported + return t.completelyImported.SetClass("alert w-full block").SetStyle("padding: 0.5rem") + } + + if (hasNearby.length === 0) { + // All points can be imported + return t.nothingNearby.SetClass("thanks w-full block").SetStyle("padding: 0.5rem") + + } + + return new Combine([ + t.someNearby.Subs({ + hasNearby: hasNearby.length, + distance: maxDistance.data + }).SetClass("alert"), + t.wontBeImported, + comparisonMap.SetClass("w-full") + ]).SetClass("w-full") })) - - + + ]).SetClass("flex flex-col") }, [allNotesWithinBbox.features, allNotesWithinBbox.state]) diff --git a/UI/ImportFlow/ConfirmProcess.ts b/UI/ImportFlow/ConfirmProcess.ts index 0cdf28be7..c8e3f570e 100644 --- a/UI/ImportFlow/ConfirmProcess.ts +++ b/UI/ImportFlow/ConfirmProcess.ts @@ -2,45 +2,31 @@ import Combine from "../Base/Combine"; import {FlowStep} from "./FlowStep"; import {UIEventSource} from "../../Logic/UIEventSource"; import Link from "../Base/Link"; -import {FixedUiElement} from "../Base/FixedUiElement"; import CheckBoxes from "../Input/Checkboxes"; import Title from "../Base/Title"; -import {SubtleButton} from "../Base/SubtleButton"; -import Svg from "../../Svg"; -import {Utils} from "../../Utils"; +import Translations from "../i18n/Translations"; export class ConfirmProcess extends Combine implements FlowStep<{ features: any[], theme: string }> { public IsValid: UIEventSource - public Value: UIEventSource<{ features: any[],theme: string }> + public Value: UIEventSource<{ features: any[], theme: string }> - constructor(v: { features: any[], theme: string }) { + constructor(v: { features: any[], theme: string }) { + const t = Translations.t.importHelper.confirmProcess; + const elements = [ + new Link(t.readImportGuidelines, "https://wiki.openstreetmap.org/wiki/Import_guidelines", true), + t.contactedCommunity, + t.licenseIsCompatible, + t.wikipageIsMade + ] + const toConfirm = new CheckBoxes(elements); - const toConfirm = [ - new Combine(["I have read the ", new Link("import guidelines on the OSM wiki", "https://wiki.openstreetmap.org/wiki/Import_guidelines", true)]), - new FixedUiElement("I did contact the (local) community about this import"), - new FixedUiElement("The license of the data to import allows it to be imported into OSM. They are allowed to be redistributed commercially, with only minimal attribution"), - new FixedUiElement("The process is documented on the OSM-wiki (you'll need this link later)") - ]; - - const licenseClear = new CheckBoxes(toConfirm) super([ - new Title("Did you go through the import process?"), - licenseClear, - new FixedUiElement("Alternatively, you can download the dataset to import directly"), - new SubtleButton(Svg.download_svg(), "Download geojson").OnClickWithLoading("Preparing your download", - async ( ) => { - const geojson = { - type:"FeatureCollection", - features: v.features - } - Utils.offerContentsAsDownloadableFile(JSON.stringify(geojson), "prepared_import_"+v.theme+".geojson",{ - mimetype: "application/vnd.geo+json" - }) - }) + new Title(t.titleLong), + toConfirm, ]); this.SetClass("link-underline") - this.IsValid = licenseClear.GetValue().map(selected => toConfirm.length == selected.length) + this.IsValid = toConfirm.GetValue().map(selected => elements.length == selected.length) this.Value = new UIEventSource<{ features: any[], theme: string }>(v) } } \ No newline at end of file diff --git a/UI/ImportFlow/ConflationChecker.ts b/UI/ImportFlow/ConflationChecker.ts index f0a3f17c9..3ae2103f8 100644 --- a/UI/ImportFlow/ConflationChecker.ts +++ b/UI/ImportFlow/ConflationChecker.ts @@ -7,7 +7,6 @@ import {UIEventSource} from "../../Logic/UIEventSource"; import Constants from "../../Models/Constants"; import RelationsTracker from "../../Logic/Osm/RelationsTracker"; import {VariableUiElement} from "../Base/VariableUIElement"; -import {FixedUiElement} from "../Base/FixedUiElement"; import {FlowStep} from "./FlowStep"; import Loading from "../Base/Loading"; import {SubtleButton} from "../Base/SubtleButton"; @@ -28,6 +27,7 @@ import * as import_candidate from "../../assets/layers/import_candidate/import_c import {GeoOperations} from "../../Logic/GeoOperations"; import FeatureInfoBox from "../Popup/FeatureInfoBox"; import {ImportUtils} from "./ImportUtils"; +import Translations from "../i18n/Translations"; /** * Given the data to import, the bbox and the layer, will query overpass for similar items @@ -47,6 +47,27 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea const toImport: {features: any[]} = params; let overpassStatus = new UIEventSource<{ error: string } | "running" | "success" | "idle" | "cached">("idle") const cacheAge = new UIEventSource(undefined); + + + function loadDataFromOverpass(){ + // Load the data! + const url = Constants.defaultOverpassUrls[1] + const relationTracker = new RelationsTracker() + const overpass = new Overpass(params.layer.source.osmTags, [], url, new UIEventSource(180), relationTracker, true) + console.log("Loading from overpass!") + overpassStatus.setData("running") + overpass.queryGeoJson(bbox).then( + ([data, date]) => { + console.log("Received overpass-data: ", data.features.length, "features are loaded at ", date); + overpassStatus.setData("success") + fromLocalStorage.setData([data, date]) + }, + (error) => { + overpassStatus.setData({error}) + }) + } + + const fromLocalStorage = IdbLocalStorage.Get<[any, Date]>("importer-overpass-cache-" + layer.id, { whenLoaded: (v) => { @@ -63,22 +84,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea } cacheAge.setData(-1) } - // Load the data! - const url = Constants.defaultOverpassUrls[1] - const relationTracker = new RelationsTracker() - const overpass = new Overpass(params.layer.source.osmTags, [], url, new UIEventSource(180), relationTracker, true) - console.log("Loading from overpass!") - overpassStatus.setData("running") - overpass.queryGeoJson(bbox).then( - ([data, date]) => { - console.log("Received overpass-data: ", data.features.length, "features are loaded at ", date); - overpassStatus.setData("success") - fromLocalStorage.setData([data, date]) - }, - (error) => { - overpassStatus.setData({error}) - }) - + loadDataFromOverpass() } }); @@ -166,7 +172,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea return osmData.features.filter(f => toImport.features.some(imp => maxDist >= GeoOperations.distanceBetween(imp.geometry.coordinates, GeoOperations.centerpointCoordinates(f)))) - }, [nearbyCutoff.GetValue()]), false); + }, [nearbyCutoff.GetValue().stabilized(500)]), false); const paritionedImport = ImportUtils.partitionFeaturesIfNearby(toImport, geojson, nearbyCutoff.GetValue().map(Number)); // Featuresource showing OSM-features which are nearby a toImport-feature @@ -190,6 +196,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea features: toImportWithNearby }) + const t = Translations.t.importHelper.conflationChecker const conflationMaps = new Combine([ new VariableUiElement( @@ -197,7 +204,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea if (geojson === undefined) { return undefined; } - return new SubtleButton(Svg.download_svg(), "Download the loaded geojson from overpass").onClick(() => { + return new SubtleButton(Svg.download_svg(), t.downloadOverpassData).onClick(() => { Utils.offerContentsAsDownloadableFile(JSON.stringify(geojson, null, " "), "mapcomplete-" + layer.id + ".geojson", { mimetype: "application/json+geo" }) @@ -208,43 +215,57 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea return undefined; } if (age < 0) { - return new FixedUiElement("Cache was expired") + return t.cacheExpired } - return new FixedUiElement("Loaded data is from the cache and is " + Utils.toHumanTime(age) + " old") + return new Combine([t.loadedDataAge.Subs({age: Utils.toHumanTime(age)}), + new SubtleButton(Svg.reload_svg().SetClass("h-8"), t.reloadTheCache) + .onClick(loadDataFromOverpass) + .SetClass("h-12") + ]) })), - new Title("Live data on OSM"), - "The "+toImport.features.length+" red elements on the following map are all your import candidates.", - new VariableUiElement(geojson.map(geojson => new FixedUiElement((geojson?.features?.length ?? "No") + " elements are loaded from OpenStreetMap which match the layer "+layer.id+". Zooming in might be needed to show them"))), + new Title(t.titleLive), + t.importCandidatesCount.Subs({count:toImport.features.length }), + new VariableUiElement(geojson.map(geojson => { + if(geojson?.features?.length === undefined || geojson?.features?.length === 0){ + return t.nothingLoaded.Subs(layer).SetClass("alert") + } + return new Combine([ + t.osmLoaded.Subs({count: geojson.features.length, name: layer.name}), + + ]) + })), osmLiveData, - new Combine(["The live data is shown if the zoomlevel is at least ", zoomLevel, ". The current zoom level is ", new VariableUiElement(osmLiveData.location.map(l => "" + l.zoom))]).SetClass("flex"), - - new Title("Nearby features"), - new Combine(["The following map shows features to import which have an OSM-feature within ", nearbyCutoff, "meter"]).SetClass("flex"), + new VariableUiElement(osmLiveData.location.map(location => { + return t.zoomIn.Subs({needed:zoomLevel, current: location.zoom }) + } )), + new Title(t.titleNearby), + new Combine([t.mapShowingNearbyIntro, nearbyCutoff]).SetClass("flex"), new VariableUiElement(toImportWithNearby.features.map(feats => - new FixedUiElement("The "+ feats.length +" red elements on the following map will not be imported!").SetClass("alert"))), - "Set the range to 0 or 1 if you want to import them all", + t.nearbyWarn.Subs({count: feats.length}).SetClass("alert"))), + t.setRangeToZero, matchedFeaturesMap]).SetClass("flex flex-col") super([ - new Title("Comparison with existing data"), + new Title(t.title), new VariableUiElement(overpassStatus.map(d => { if (d === "idle") { - return new Loading("Checking local storage...") - } - if (d["error"] !== undefined) { - return new FixedUiElement("Could not load latest data from overpass: " + d["error"]).SetClass("alert") + return new Loading(t.states.idle) } if (d === "running") { - return new Loading("Querying overpass...") + return new Loading(t.states.running) } + if (d["error"] !== undefined) { + return t.states.error.Subs({error: d["error"]}).SetClass("alert") + } + if (d === "cached") { return conflationMaps } if (d === "success") { return conflationMaps } - return new FixedUiElement("Unexpected state " + d).SetClass("alert") + return t.states.unexpected.Subs({state: d}).SetClass("alert") })) ]) diff --git a/UI/ImportFlow/CreateNotes.ts b/UI/ImportFlow/CreateNotes.ts index 1364d3675..249be836e 100644 --- a/UI/ImportFlow/CreateNotes.ts +++ b/UI/ImportFlow/CreateNotes.ts @@ -8,47 +8,72 @@ import {VariableUiElement} from "../Base/VariableUIElement"; import {FixedUiElement} from "../Base/FixedUiElement"; import {SubtleButton} from "../Base/SubtleButton"; import Svg from "../../Svg"; +import Translations from "../i18n/Translations"; +import {Translation} from "../i18n/Translation"; export class CreateNotes extends Combine { + + + public static createNoteContentsUi(feature: {properties: any, geometry: {coordinates: [number,number]}}, + options: {wikilink: string; intro: string; source: string, theme: string } + ): (Translation | string)[]{ + const src = feature.properties["source"] ?? feature.properties["src"] ?? options.source + delete feature.properties["source"] + delete feature.properties["src"] + let extraNote = "" + if (feature.properties["note"]) { + extraNote = feature.properties["note"] + "\n" + delete feature.properties["note"] + } + + const tags: string [] = [] + for (const key in feature.properties) { + if (feature.properties[key] === null || feature.properties[key] === undefined) { + console.warn("Null or undefined key for ", feature.properties) + continue + } + if (feature.properties[key] === "") { + continue + } + tags.push(key + "=" + (feature.properties[key]+"").replace(/=/, "\\=").replace(/;/g, "\\;").replace(/\n/g, "\\n")) + } + const lat = feature.geometry.coordinates[1] + const lon = feature.geometry.coordinates[0] + const note = Translations.t.importHelper.noteParts + return [ + options.intro, + extraNote, + note.datasource.Subs({source: src}), + note.wikilink.Subs(options), + '', + note.importEasily, + `https://mapcomplete.osm.be/${options.theme}.html?z=18&lat=${lat}&lon=${lon}#import`, + ...tags] + } + + public static createNoteContents(feature: {properties: any, geometry: {coordinates: [number,number]}}, + options: {wikilink: string; intro: string; source: string, theme: string } + ): string[]{ + return CreateNotes.createNoteContentsUi(feature, options).map(trOrStr => { + if(typeof trOrStr === "string"){ + return trOrStr + } + return trOrStr.txt + }) + } + constructor(state: { osmConnection: OsmConnection }, v: { features: any[]; wikilink: string; intro: string; source: string, theme: string }) { - + const t = Translations.t.importHelper.createNotes; const createdNotes: UIEventSource = new UIEventSource([]) const failed = new UIEventSource([]) const currentNote = createdNotes.map(n => n.length) for (const f of v.features) { - - const src = f.properties["source"] ?? f.properties["src"] ?? v.source - delete f.properties["source"] - delete f.properties["src"] - let extraNote = "" - if (f.properties["note"]) { - extraNote = f.properties["note"] + "\n" - delete f.properties["note"] - } - - const tags: string [] = [] - for (const key in f.properties) { - if (f.properties[key] === null || f.properties[key] === undefined) { - console.warn("Null or undefined key for ", f.properties) - continue - } - if (f.properties[key] === "") { - continue - } - tags.push(key + "=" + (f.properties[key]+"").replace(/=/, "\\=").replace(/;/g, "\\;").replace(/\n/g, "\\n")) - } + const lat = f.geometry.coordinates[1] const lon = f.geometry.coordinates[0] - const text = [v.intro, - extraNote, - "Source: " + src, - 'More information at ' + v.wikilink, - '', - 'Import this point easily with', - `https://mapcomplete.osm.be/${v.theme}.html?z=18&lat=${lat}&lon=${lon}#import`, - ...tags].join("\n") + const text = CreateNotes.createNoteContents(f, v).join("\n") state.osmConnection.openNote( lat, lon, text) @@ -62,13 +87,19 @@ export class CreateNotes extends Combine { } super([ - new Title("Creating notes"), - "Hang on while we are importing...", + new Title(t.title), + t.loading , new Toggle( - new Loading(new VariableUiElement(currentNote.map(count => new FixedUiElement("Imported " + count + " out of " + v.features.length + " notes")))), + new Loading(new VariableUiElement(currentNote.map(count => t.creating.Subs({ + count, total: v.features.length + } + + )))), new Combine([ - new FixedUiElement("All done!").SetClass("thanks"), - new SubtleButton(Svg.note_svg(), "Inspect the progress of your notes in the 'import_viewer'", { + Svg.party_svg().SetClass("w-24"), + t.done.Subs({count: v.features.length}).SetClass("thanks"), + new SubtleButton(Svg.note_svg(), + t.openImportViewer , { url: "import_viewer.html" }) ] diff --git a/UI/ImportFlow/FlowStep.ts b/UI/ImportFlow/FlowStep.ts index e0fde7b60..694207bcb 100644 --- a/UI/ImportFlow/FlowStep.ts +++ b/UI/ImportFlow/FlowStep.ts @@ -25,15 +25,15 @@ export class FlowPanelFactory { this._stepNames = stepNames; } - public static start(name: string | BaseUIElement, step: FlowStep): FlowPanelFactory { - return new FlowPanelFactory(step, [], [name]) + public static start(name:{title: BaseUIElement}, step: FlowStep): FlowPanelFactory { + return new FlowPanelFactory(step, [], [name.title]) } - public then(name: string | BaseUIElement, construct: ((t: T) => FlowStep)): FlowPanelFactory { + public then(name: string | {title: BaseUIElement}, construct: ((t: T) => FlowStep)): FlowPanelFactory { return new FlowPanelFactory( this._initial, this._steps.concat([construct]), - this._stepNames.concat([name]) + this._stepNames.concat([name["title"] ?? name]) ) } @@ -120,11 +120,11 @@ export class FlowPanel extends Toggle { isError.setData(true) } }), - "Select a valid value to continue", + new SubtleButton(Svg.invalid_svg(), t.notValid), initial.IsValid ), new Toggle( - new FixedUiElement("Something went wrong...").SetClass("alert"), + t.error.SetClass("alert"), undefined, isError), ]).SetClass("flex w-full justify-end space-x-2"), diff --git a/UI/ImportFlow/ImportHelperGui.ts b/UI/ImportFlow/ImportHelperGui.ts index 8fb1c041b..000cae352 100644 --- a/UI/ImportFlow/ImportHelperGui.ts +++ b/UI/ImportFlow/ImportHelperGui.ts @@ -7,7 +7,7 @@ import MinimapImplementation from "../Base/MinimapImplementation"; import Translations from "../i18n/Translations"; import {FlowPanelFactory} from "./FlowStep"; import {RequestFile} from "./RequestFile"; -import {PreviewPanel} from "./PreviewPanel"; +import {PreviewAttributesPanel} from "./PreviewPanel"; import ConflationChecker from "./ConflationChecker"; import {AskMetadata} from "./AskMetadata"; import {ConfirmProcess} from "./ConfirmProcess"; @@ -26,20 +26,20 @@ import SelectTheme from "./SelectTheme"; export default class ImportHelperGui extends LeftIndex { constructor() { const state = new UserRelatedState(undefined) - + const t = Translations.t.importHelper; const {flow, furthestStep, titles} = FlowPanelFactory - .start("Introduction", new Introdution()) - .then("Login", _ => new LoginToImport(state)) - .then("Select file", _ => new RequestFile()) - .then("Inspect attributes", geojson => new PreviewPanel(state, geojson)) - .then("Inspect data", geojson => new MapPreview(state, geojson)) - .then("Select theme", v => new SelectTheme(v)) - .then("Compare with open notes", v => new CompareToAlreadyExistingNotes(state, v)) - .then("Compare with existing data", v => new ConflationChecker(state, v)) - .then("License and community check", v => new ConfirmProcess(v)) - .then("Metadata", (v) => new AskMetadata(v)) - .finish("Note creation", v => new CreateNotes(state, v)); + .start(t.introduction, new Introdution()) + .then(t.login, _ => new LoginToImport(state)) + .then(t.selectFile, _ => new RequestFile()) + .then(t.previewAttributes, geojson => new PreviewAttributesPanel(state, geojson)) + .then(t.mapPreview, geojson => new MapPreview(state, geojson)) + .then(t.selectTheme, v => new SelectTheme(v)) + .then(t.compareToAlreadyExistingNotes, v => new CompareToAlreadyExistingNotes(state, v)) + .then(t.conflationChecker, v => new ConflationChecker(state, v)) + .then(t.confirmProcess, v => new ConfirmProcess(v)) + .then(t.askMetadata, (v) => new AskMetadata(v)) + .finish(t.createNotes.title, v => new CreateNotes(state, v)); const toc = new List( titles.map((title, i) => new VariableUiElement(furthestStep.map(currentStep => { @@ -58,11 +58,11 @@ export default class ImportHelperGui extends LeftIndex { , true) const leftContents: BaseUIElement[] = [ - new SubtleButton(undefined, "Inspect your preview imports", { + new SubtleButton(undefined, t.gotoImportViewer, { url: "import_viewer.html" }), toc, - new Toggle(new FixedUiElement("Testmode - won't actually import notes").SetClass("alert"), undefined, state.featureSwitchIsTesting), + new Toggle(t.testMode.SetClass("block alert"), undefined, state.featureSwitchIsTesting), LanguagePicker.CreateLanguagePicker(Translations.t.importHelper.title.SupportedLanguages())?.SetClass("mt-4 self-end flex-col"), ].map(el => el?.SetClass("pl-4")) diff --git a/UI/ImportFlow/Introdution.ts b/UI/ImportFlow/Introdution.ts index 859fd8e4b..d80090196 100644 --- a/UI/ImportFlow/Introdution.ts +++ b/UI/ImportFlow/Introdution.ts @@ -3,18 +3,43 @@ import {FlowStep} from "./FlowStep"; import {UIEventSource} from "../../Logic/UIEventSource"; import Translations from "../i18n/Translations"; import Title from "../Base/Title"; +import {CreateNotes} from "./CreateNotes"; +import {FixedUiElement} from "../Base/FixedUiElement"; export default class Introdution extends Combine implements FlowStep { - readonly IsValid: UIEventSource = new UIEventSource(true); - readonly Value: UIEventSource = new UIEventSource(undefined); + readonly IsValid: UIEventSource; + readonly Value: UIEventSource; constructor() { + const example = CreateNotes.createNoteContentsUi({ + properties:{ + "some_key":"some_value", + "note":"a note in the original dataset" + }, + geometry:{ + coordinates: [3.4,51.2] + } + }, { + wikilink: "https://wiki.openstreetmap.org/wiki/Imports/", + intro: "There might be an XYZ here", + theme: "theme", + source: "source of the data" + }).map(el => el === "" ? new FixedUiElement("").SetClass("block") : el) + super([ - new Title(Translations.t.importHelper.title), - Translations.t.importHelper.description, - Translations.t.importHelper.importFormat, + new Title(Translations.t.importHelper.introduction.title), + Translations.t.importHelper.introduction.description, + Translations.t.importHelper.introduction.importFormat, + new Combine( + [new Combine( + example + ).SetClass("flex flex-col") + ] ).SetClass("literal-code") ]); this.SetClass("flex flex-col") + this. IsValid= new UIEventSource(true); + this. Value = new UIEventSource(undefined); + } } \ No newline at end of file diff --git a/UI/ImportFlow/LoginToImport.ts b/UI/ImportFlow/LoginToImport.ts index 3c5df6e67..8a73042ce 100644 --- a/UI/ImportFlow/LoginToImport.ts +++ b/UI/ImportFlow/LoginToImport.ts @@ -21,7 +21,7 @@ export default class LoginToImport extends Combine implements FlowStep t.loginIsCorrect.Subs(ud)))]) const isValid = state.osmConnection.userDetails.map(ud => LoginToImport.whitelist.indexOf(ud.uid) >= 0 || ud.csCount >= Constants.userJourney.importHelperUnlock) diff --git a/UI/ImportFlow/PreviewPanel.ts b/UI/ImportFlow/PreviewPanel.ts index fab9440c0..8d5495004 100644 --- a/UI/ImportFlow/PreviewPanel.ts +++ b/UI/ImportFlow/PreviewPanel.ts @@ -12,16 +12,16 @@ import List from "../Base/List"; import CheckBoxes from "../Input/Checkboxes"; /** - * Shows the data to import on a map, asks for the correct layer to be selected + * Shows the attributes by value, requests to check them of */ -export class PreviewPanel extends Combine implements FlowStep<{ features: { properties: any, geometry: { coordinates: [number, number] } }[] }> { +export class PreviewAttributesPanel extends Combine implements FlowStep<{ features: { properties: any, geometry: { coordinates: [number, number] } }[] }> { public readonly IsValid: UIEventSource; public readonly Value: UIEventSource<{ features: { properties: any, geometry: { coordinates: [number, number] } }[] }> constructor( state: UserRelatedState, geojson: { features: { properties: any, geometry: { coordinates: [number, number] } }[] }) { - const t = Translations.t.importHelper; + const t = Translations.t.importHelper.previewAttributes; const propertyKeys = new Set() for (const f of geojson.features) { diff --git a/UI/ImportFlow/SelectTheme.ts b/UI/ImportFlow/SelectTheme.ts index 1a84aee0f..99339ab62 100644 --- a/UI/ImportFlow/SelectTheme.ts +++ b/UI/ImportFlow/SelectTheme.ts @@ -10,12 +10,12 @@ import Title from "../Base/Title"; import {RadioButton} from "../Input/RadioButton"; import {And} from "../../Logic/Tags/And"; import {VariableUiElement} from "../Base/VariableUIElement"; -import {FixedUiElement} from "../Base/FixedUiElement"; import Toggleable from "../Base/Toggleable"; import {BBox} from "../../Logic/BBox"; import BaseUIElement from "../BaseUIElement"; import PresetConfig from "../../Models/ThemeConfig/PresetConfig"; import List from "../Base/List"; +import Translations from "../i18n/Translations"; export default class SelectTheme extends Combine implements FlowStep<{ features: any[], @@ -33,7 +33,7 @@ export default class SelectTheme extends Combine implements FlowStep<{ public readonly IsValid: UIEventSource; constructor(params: ({ features: any[], layer: LayerConfig, bbox: BBox, })) { - + const t = Translations.t.importHelper.selectTheme let options: InputElement[] = AllKnownLayouts.layoutsList .filter(th => th.layers.some(l => l.id === params.layer.id)) .filter(th => th.id !== "personal") @@ -69,15 +69,15 @@ export default class SelectTheme extends Combine implements FlowStep<{ }) super([ - new Title("Select a theme"), - "All of the following themes will show the import notes. However, the note on OpenStreetMap can link to only one single theme. Choose which theme that the created notes will link to", + new Title(t.title), + t.intro, themeRadios, new VariableUiElement(applicablePresets.map(applicablePresets => { if (themeRadios.GetValue().data === undefined) { return undefined } if (applicablePresets === undefined || applicablePresets.length === 0) { - return new FixedUiElement("This theme has no presets loaded. As a result, imports won't work here").SetClass("alert") + return t.noMatchingPresets.SetClass("alert") } }, [themeRadios.GetValue()])), @@ -115,11 +115,14 @@ export default class SelectTheme extends Combine implements FlowStep<{ if (unmatched === undefined || unmatched.length === 0) { return } - - const applicablePresetsOverview = applicablePresets.map(preset => new Combine([ - preset.title.txt, "needs tags", - new FixedUiElement(preset.tags.map(t => t.asHumanString()).join(" & ")).SetClass("thanks") - ])) + const t = Translations.t.importHelper.selectTheme + + const applicablePresetsOverview = applicablePresets.map(preset => + t.needsTags.Subs( + {title: preset.title, + tags:preset.tags.map(t => t.asHumanString()).join(" & ") }) + .SetClass("thanks") + ); const unmatchedPanels: BaseUIElement[] = [] for (const feat of unmatched) { @@ -133,20 +136,16 @@ export default class SelectTheme extends Combine implements FlowStep<{ const missing = [] for (const {k, v} of tags) { if (preset[k] === undefined) { - missing.push( - `Expected ${k}=${v}, but it is completely missing` - ) + missing.push(t.missing.Subs({k,v})) } else if (feat.properties[k] !== v) { - missing.push( - `Property with key ${k} does not have expected value ${v}; instead it is ${feat.properties}` - ) + missing.push(t.misMatch.Subs({k, v, properties: feat.properties})) } } if (missing.length > 0) { parts.push( new Combine([ - new FixedUiElement(`Preset ${preset.title.txt} is not applicable:`), + t.notApplicable.Subs(preset), new List(missing) ]).SetClass("flex flex-col alert") ) @@ -158,9 +157,9 @@ export default class SelectTheme extends Combine implements FlowStep<{ } return new Combine([ - new FixedUiElement(unmatched.length + " objects dont match any presets").SetClass("alert"), + t.displayNonMatchingCount.Subs(unmatched).SetClass("alert"), ...applicablePresetsOverview, - new Toggleable(new Title("The following elements don't match any of the presets"), + new Toggleable(new Title(t.unmatchedTitle), new Combine(unmatchedPanels)) ]).SetClass("flex flex-col") diff --git a/UI/Input/DropDown.ts b/UI/Input/DropDown.ts index d7137a04b..b9fb6a3d3 100644 --- a/UI/Input/DropDown.ts +++ b/UI/Input/DropDown.ts @@ -47,7 +47,7 @@ export class DropDown extends InputElement { } options = options ?? {} - options.select_class = options.select_class ?? 'bg-indigo-100 p-1 rounded hover:bg-indigo-200' + options.select_class = options.select_class ?? 'w-full bg-indigo-100 p-1 rounded hover:bg-indigo-200' { diff --git a/UI/Input/InputElementWrapper.ts b/UI/Input/InputElementWrapper.ts index 9006956c5..623fc18d5 100644 --- a/UI/Input/InputElementWrapper.ts +++ b/UI/Input/InputElementWrapper.ts @@ -9,7 +9,8 @@ export default class InputElementWrapper extends InputElement { private readonly _inputElement: InputElement; private readonly _renderElement: BaseUIElement - constructor(inputElement: InputElement, translation: Translation, key: string, tags: UIEventSource, state: FeaturePipelineState) { + constructor(inputElement: InputElement, translation: Translation, key: string, + tags: UIEventSource, state: FeaturePipelineState) { super() this._inputElement = inputElement; const mapping = new Map() diff --git a/UI/Input/ValidatedTextField.ts b/UI/Input/ValidatedTextField.ts index 874e830bc..15fe25b7e 100644 --- a/UI/Input/ValidatedTextField.ts +++ b/UI/Input/ValidatedTextField.ts @@ -250,13 +250,15 @@ class WikidataTextField extends TextFieldDef { ["subarg", "doc"], [["removePrefixes", "remove these snippets of text from the start of the passed string to search"], ["removePostfixes", "remove these snippets of text from the end of the passed string to search"], + ["instanceOf","A list of Q-identifier which indicates that the search results _must_ be an entity of this type, e.g. [`Q5`](https://www.wikidata.org/wiki/Q5) for humans"], + ["notInstanceof","A list of Q-identifiers which indicates that the search results _must not_ be an entity of this type, e.g. [`Q79007`](https://www.wikidata.org/wiki/Q79007) to filter away all streets from the search results"] ] )]) ]]), new Title("Example usage"), `The following is the 'freeform'-part of a layer config which will trigger a search for the wikidata item corresponding with the name of the selected feature. It will also remove '-street', '-square', ... if found at the end of the name -\`\`\` +\`\`\`json "freeform": { "key": "name:etymology:wikidata", "type": "wikidata", @@ -269,11 +271,29 @@ class WikidataTextField extends TextFieldDef { "path", "square", "plaza", - ] + ], + "#": "Remove streets and parks from the search results:" + "notInstanceOf": ["Q79007","Q22698"] } + ] } -\`\`\`` +\`\`\` + +Another example is to search for species and trees: + +\`\`\`json + "freeform": { + "key": "species:wikidata", + "type": "wikidata", + "helperArgs": [ + "species", + { + "instanceOf": [10884, 16521] + }] + } +\`\`\` +` ])); } @@ -304,9 +324,9 @@ class WikidataTextField extends TextFieldDef { const args = inputHelperOptions.args ?? [] const searchKey = args[0] ?? "name" - let searchFor = inputHelperOptions.feature?.properties[searchKey]?.toLowerCase() + let searchFor = (inputHelperOptions.feature?.properties[searchKey]?.toLowerCase() ?? "") - const options = args[1] + const options: any = args[1] if (searchFor !== undefined && options !== undefined) { const prefixes = options["removePrefixes"] const postfixes = options["removePostfixes"] @@ -325,10 +345,18 @@ class WikidataTextField extends TextFieldDef { } } + + let instanceOf : number[] = Utils.NoNull((options?.instanceOf ?? []).map(i => Wikidata.QIdToNumber(i))) + let notInstanceOf : number[] = Utils.NoNull((options?.notInstanceOf ?? []).map(i => Wikidata.QIdToNumber(i))) + console.log("Instance of", instanceOf) + + return new WikidataSearchBox({ value: currentValue, - searchText: new UIEventSource(searchFor) + searchText: new UIEventSource(searchFor), + instanceOf, + notInstanceOf }) } } @@ -424,7 +452,7 @@ class UrlTextfieldDef extends TextFieldDef { reformat(str: string): string { try { let url: URL - str = str.toLowerCase() + // str = str.toLowerCase() // URLS are case sensitive. Lowercasing them might break some URLS. See #763 if (!str.startsWith("http://") && !str.startsWith("https://") && !str.startsWith("http:")) { url = new URL("https://" + str) } else { diff --git a/UI/Popup/DeleteWizard.ts b/UI/Popup/DeleteWizard.ts index ba289a2e2..1cfece179 100644 --- a/UI/Popup/DeleteWizard.ts +++ b/UI/Popup/DeleteWizard.ts @@ -202,7 +202,7 @@ export default class DeleteWizard extends Toggle { private static generateDeleteTagRenderingConfig(softDeletionTags: TagsFilter, nonDeleteOptions: { if: TagsFilter; then: Translation }[], extraDeleteReasons: { explanation: Translation; changesetMessage: string }[], - currentTags: any) { + currentTags: any): TagRenderingConfig { const t = Translations.t.delete nonDeleteOptions = nonDeleteOptions ?? [] let softDeletionTagsStr = [] diff --git a/UI/Popup/ImportButton.ts b/UI/Popup/ImportButton.ts index 4108c4e24..8db42618d 100644 --- a/UI/Popup/ImportButton.ts +++ b/UI/Popup/ImportButton.ts @@ -194,7 +194,7 @@ ${Utils.special_visualizations_importRequirementDocs} importFlow, isImported ), - t.zoomInMore.SetClass("alert"), + t.zoomInMore.SetClass("alert block"), state.locationControl.map(l => l.zoom >= 18) ), pleaseLoginButton, @@ -613,7 +613,7 @@ export class ImportPointButton extends AbstractImportButton { icon: () => new Img(args.icon), layerToAddTo: state.filteredLayers.data.filter(l => l.layerDef.id === args.targetLayer)[0], name: args.text, - title: Translations.WT(args.text), + title: Translations.T(args.text), preciseInput: preciseInputSpec, // must be explicitely assigned, if 'undefined' won't work otherwise boundsFactor: 3 } diff --git a/UI/Popup/MoveWizard.ts b/UI/Popup/MoveWizard.ts index 6ed7d0657..b6eb6e712 100644 --- a/UI/Popup/MoveWizard.ts +++ b/UI/Popup/MoveWizard.ts @@ -86,7 +86,7 @@ export default class MoveWizard extends Toggle { moveReason.setData(reason) moveButton = new SubtleButton( reason.icon.SetStyle("height: 1.5rem; width: 1.5rem;"), - Translations.WT(reason.invitingText) + Translations.T(reason.invitingText) ).onClick(() => { currentStep.setData("pick_location") }) diff --git a/UI/Popup/TagRenderingQuestion.ts b/UI/Popup/TagRenderingQuestion.ts index a20019d99..7e32b1263 100644 --- a/UI/Popup/TagRenderingQuestion.ts +++ b/UI/Popup/TagRenderingQuestion.ts @@ -11,7 +11,7 @@ import {SaveButton} from "./SaveButton"; import {VariableUiElement} from "../Base/VariableUIElement"; import Translations from "../i18n/Translations"; import {FixedUiElement} from "../Base/FixedUiElement"; -import {Translation} from "../i18n/Translation"; +import {Translation, TypedTranslation} from "../i18n/Translation"; import Constants from "../../Models/Constants"; import {SubstitutedTranslation} from "../SubstitutedTranslation"; import {TagsFilter} from "../../Logic/Tags/TagsFilter"; @@ -51,7 +51,7 @@ export default class TagRenderingQuestion extends Combine { const applicableMappingsSrc = UIEventSource.ListStabilized(tags.map(tags => { - const applicableMappings: { if: TagsFilter, then: any, ifnot?: TagsFilter, addExtraTags: Tag[] }[] = [] + const applicableMappings: { if: TagsFilter, icon?: string, then: TypedTranslation, ifnot?: TagsFilter, addExtraTags: Tag[] }[] = [] for (const mapping of configuration.mappings ?? []) { if (mapping.hideInAnswer === true) { continue @@ -158,7 +158,7 @@ export default class TagRenderingQuestion extends Combine { private static GenerateInputElement( state, configuration: TagRenderingConfig, - applicableMappings: { if: TagsFilter, then: any, ifnot?: TagsFilter, addExtraTags: Tag[] }[], + applicableMappings: { if: TagsFilter, then: TypedTranslation, icon?: string, ifnot?: TagsFilter, addExtraTags: Tag[] }[], applicableUnit: Unit, tagsSource: UIEventSource, feedback: UIEventSource @@ -168,7 +168,7 @@ export default class TagRenderingQuestion extends Combine { const ff = TagRenderingQuestion.GenerateFreeform(state, configuration, applicableUnit, tagsSource, feedback); - const hasImages = applicableMappings.findIndex(mapping => mapping.then.icon !== undefined) >= 0 + const hasImages = applicableMappings.findIndex(mapping => mapping.icon !== undefined) >= 0 let inputEls: InputElement[]; const ifNotsPresent = applicableMappings.some(mapping => mapping.ifnot !== undefined) @@ -207,7 +207,7 @@ export default class TagRenderingQuestion extends Combine { applicableMappings.map((mapping, i) => { return { value: new And([mapping.if, ...allIfNotsExcept(i)]), - shown: Translations.WT(mapping.then) + shown: mapping.then.Subs(tagsSource.data) } }) ) @@ -248,7 +248,7 @@ export default class TagRenderingQuestion extends Combine { const inputEl = new InputElementMap( checkBoxes, (t0, t1) => { - return t0?.isEquivalent(t1) ?? false + return t0?.shadows(t1) ?? false }, (indices) => { if (indices.length === 0) { @@ -370,7 +370,7 @@ export default class TagRenderingQuestion extends Combine { return new FixedInputElement( TagRenderingQuestion.GenerateMappingContent(mapping, tagsSource, state), tagging, - (t0, t1) => t1.isEquivalent(t0)); + (t0, t1) => t1.shadows(t0)); } private static GenerateMappingContent(mapping: { @@ -450,7 +450,7 @@ export default class TagRenderingQuestion extends Combine { }) let inputTagsFilter: InputElement = new InputElementMap( - input, (a, b) => a === b || (a?.isEquivalent(b) ?? false), + input, (a, b) => a === b || (a?.shadows(b) ?? false), pickString, toString ); diff --git a/UI/Reviews/ReviewElement.ts b/UI/Reviews/ReviewElement.ts index 526160b11..79fe40132 100644 --- a/UI/Reviews/ReviewElement.ts +++ b/UI/Reviews/ReviewElement.ts @@ -25,7 +25,7 @@ export default class ReviewElement extends VariableUiElement { SingleReview.GenStars(avg), new Link( revs.length === 1 ? Translations.t.reviews.title_singular.Clone() : - Translations.t.reviews.title.Clone() + Translations.t.reviews.title .Subs({count: "" + revs.length}), `https://mangrove.reviews/search?sub=${encodeURIComponent(subject)}`, true diff --git a/UI/SpecialVisualizations.ts b/UI/SpecialVisualizations.ts index 046bd28f6..320355393 100644 --- a/UI/SpecialVisualizations.ts +++ b/UI/SpecialVisualizations.ts @@ -46,6 +46,8 @@ import {LoginToggle} from "./Popup/LoginButton"; import {start} from "repl"; import {SubstitutedTranslation} from "./SubstitutedTranslation"; import {TextField} from "./Input/TextField"; +import Wikidata, {WikidataResponse} from "../Logic/Web/Wikidata"; +import {Translation} from "./i18n/Translation"; export interface SpecialVisualization { funcName: string, @@ -159,19 +161,19 @@ class CloseNoteButton implements SpecialVisualization { tags.ping() }) }) - - if((params.minZoom??"") !== "" && !isNaN(Number(params.minZoom))){ - closeButton = new Toggle( + + if ((params.minZoom ?? "") !== "" && !isNaN(Number(params.minZoom))) { + closeButton = new Toggle( closeButton, params.zoomButton ?? "", - state. locationControl.map(l => l.zoom >= Number(params.minZoom)) + state.locationControl.map(l => l.zoom >= Number(params.minZoom)) ) } - + return new LoginToggle(new Toggle( t.isClosed.SetClass("thanks"), closeButton, - + isClosed ), t.loginToClose, state) } @@ -180,7 +182,7 @@ class CloseNoteButton implements SpecialVisualization { export default class SpecialVisualizations { - public static specialVisualizations : SpecialVisualization[] = SpecialVisualizations.init() + public static specialVisualizations: SpecialVisualization[] = SpecialVisualizations.init() public static HelpMessage() { @@ -207,28 +209,28 @@ export default class SpecialVisualizations { )); return new Combine([ - new Combine([ - - new Title("Special tag renderings", 1), - - "In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's.", - "General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args", - new Title("Using expanded syntax",4), - `Instead of using \`{"render": {"en": "{some_special_visualisation(some_arg, some other really long message, more args)} , "nl": "{some_special_visualisation(some_arg, een boodschap in een andere taal, more args)}}, one can also write`, - new FixedUiElement(JSON.stringify({ - render: { - special:{ - type: "some_special_visualisation", - "argname": "some_arg", - "message":{ - en:"some other really long message", - nl: "een boodschap in een andere taal" - }, - "other_arg_name":"more args" + new Combine([ + + new Title("Special tag renderings", 1), + + "In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's.", + "General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args", + new Title("Using expanded syntax", 4), + `Instead of using \`{"render": {"en": "{some_special_visualisation(some_arg, some other really long message, more args)} , "nl": "{some_special_visualisation(some_arg, een boodschap in een andere taal, more args)}}, one can also write`, + new FixedUiElement(JSON.stringify({ + render: { + special: { + type: "some_special_visualisation", + "argname": "some_arg", + "message": { + en: "some other really long message", + nl: "een boodschap in een andere taal" + }, + "other_arg_name": "more args" + } } - } - })).SetClass("code") - ]).SetClass("flex flex-col"), + })).SetClass("code") + ]).SetClass("flex flex-col"), ...helpTexts ] ).SetClass("flex flex-col"); @@ -297,6 +299,32 @@ export default class SpecialVisualizations { ) }, + { + funcName: "wikidata_label", + docs: "Shows the label of the corresponding wikidata-item", + args: [ + { + name: "keyToShowWikidataFor", + doc: "Use the wikidata entry from this key to show the label", + defaultValue: "wikidata" + } + ], + example: "`{wikidata_label()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the label itself", + constr: (_, tagsSource, args) => + new VariableUiElement( + tagsSource.map(tags => tags[args[0]]) + .map(wikidata => { + wikidata = Utils.NoEmpty(wikidata?.split(";")?.map(wd => wd.trim()) ?? [])[0] + const entry = Wikidata.LoadWikidataEntry(wikidata) + return new VariableUiElement(entry.map(e => { + if (e === undefined || e["success"] === undefined) { + return wikidata + } + const response = e["success"] + return Translation.fromMap(response.labels) + })) + })) + }, { funcName: "minimap", docs: "A small map showing the selected feature.", @@ -482,7 +510,7 @@ export default class SpecialVisualizations { docs: "Downloads a JSON from the given URL, e.g. '{live(example.org/data.json, shorthand:x.y.z, other:a.b.c, shorthand)}' will download the given file, will create an object {shorthand: json[x][y][z], other: json[a][b][c] out of it and will return 'other' or 'json[a][b][c]. This is made to use in combination with tags, e.g. {live({url}, {url:format}, needed_value)}", example: "{live({url},{url:format},hour)} {live(https://data.mobility.brussels/bike/api/counts/?request=live&featureID=CB2105,hour:data.hour_cnt;day:data.day_cnt;year:data.year_cnt,hour)}", args: [{ - name: "Url", + name: "Url", doc: "The URL to load", required: true }, { @@ -783,7 +811,7 @@ export default class SpecialVisualizations { const textField = new TextField( { placeholder: t.addCommentPlaceholder, - inputStyle: "width: 100%; height: 6rem;", + inputStyle: "width: 100%; height: 6rem;", textAreaRows: 3, htmlType: "area" } @@ -846,7 +874,7 @@ export default class SpecialVisualizations { textField, new Combine([ stateButtons.SetClass("sm:mr-2"), - new Toggle(addCommentButton, + new Toggle(addCommentButton, new Combine([t.typeText]).SetClass("flex items-center h-full subtle"), textField.GetValue().map(t => t !== undefined && t.length >= 1)).SetClass("sm:mr-2") ]).SetClass("sm:flex sm:justify-between sm:items-stretch") @@ -947,7 +975,7 @@ export default class SpecialVisualizations { ] specialVisualizations.push(new AutoApplyButton(specialVisualizations)) - + return specialVisualizations; } diff --git a/UI/Wikipedia/WikidataPreviewBox.ts b/UI/Wikipedia/WikidataPreviewBox.ts index a5f125e5c..1e6db1ca3 100644 --- a/UI/Wikipedia/WikidataPreviewBox.ts +++ b/UI/Wikipedia/WikidataPreviewBox.ts @@ -1,7 +1,7 @@ import {VariableUiElement} from "../Base/VariableUIElement"; import {UIEventSource} from "../../Logic/UIEventSource"; import Wikidata, {WikidataResponse} from "../../Logic/Web/Wikidata"; -import {Translation} from "../i18n/Translation"; +import {Translation, TypedTranslation} from "../i18n/Translation"; import {FixedUiElement} from "../Base/FixedUiElement"; import Loading from "../Base/Loading"; import Translations from "../i18n/Translations"; @@ -22,7 +22,7 @@ export default class WikidataPreviewBox extends VariableUiElement { private static extraProperties: { requires?: { p: number, q?: number }[], property: string, - display: Translation | Map BaseUIElement) /*If translation: Subs({value: * }) */> + display: TypedTranslation<{value}> | Map BaseUIElement) /*If translation: Subs({value: * }) */> }[] = [ { requires: WikidataPreviewBox.isHuman, diff --git a/UI/Wikipedia/WikidataSearchBox.ts b/UI/Wikipedia/WikidataSearchBox.ts index c3df838cd..87afd9905 100644 --- a/UI/Wikipedia/WikidataSearchBox.ts +++ b/UI/Wikipedia/WikidataSearchBox.ts @@ -17,14 +17,20 @@ export default class WikidataSearchBox extends InputElement { IsSelected: UIEventSource = new UIEventSource(false); private readonly wikidataId: UIEventSource private readonly searchText: UIEventSource + private readonly instanceOf?: number[]; + private readonly notInstanceOf?: number[]; constructor(options?: { searchText?: UIEventSource, - value?: UIEventSource + value?: UIEventSource, + notInstanceOf?: number[], + instanceOf?: number[] }) { super(); this.searchText = options?.searchText this.wikidataId = options?.value ?? new UIEventSource(undefined); + this.instanceOf = options?.instanceOf + this.notInstanceOf = options?.notInstanceOf } GetValue(): UIEventSource { @@ -59,7 +65,9 @@ export default class WikidataSearchBox extends InputElement { if (promise === undefined) { promise = Wikidata.searchAndFetch(searchText, { lang, - maxCount: 5 + maxCount: 5, + notInstanceOf: this.notInstanceOf, + instanceOf: this.instanceOf } ) WikidataSearchBox._searchCache.set(key, promise) @@ -75,13 +83,15 @@ export default class WikidataSearchBox extends InputElement { return new Combine([Translations.t.general.wikipedia.failed.Clone().SetClass("alert"), searchFailMessage.data]) } + if (searchField.GetValue().data.length === 0) { + return Translations.t.general.wikipedia.doSearch + } + if (searchResults.length === 0) { return Translations.t.general.wikipedia.noResults.Subs({search: searchField.GetValue().data ?? ""}) } - if (searchResults.length === 0) { - return Translations.t.general.wikipedia.doSearch - } + return new Combine(searchResults.map(wikidataresponse => { const el = WikidataPreviewBox.WikidataResponsePreview(wikidataresponse).SetClass("rounded-xl p-1 sm:p-2 md:p-3 m-px border-2 sm:border-4 transition-colors") diff --git a/UI/i18n/Translation.ts b/UI/i18n/Translation.ts index e9c815708..677878acc 100644 --- a/UI/i18n/Translation.ts +++ b/UI/i18n/Translation.ts @@ -1,9 +1,6 @@ import Locale from "./Locale"; import {Utils} from "../../Utils"; import BaseUIElement from "../BaseUIElement"; -import Link from "../Base/Link"; -import Svg from "../../Svg"; -import {VariableUiElement} from "../Base/VariableUIElement"; import LinkToWeblate from "../Base/LinkToWeblate"; export class Translation extends BaseUIElement { @@ -164,25 +161,7 @@ export class Translation extends BaseUIElement { public AllValues(): string[] { return this.SupportedLanguages().map(lng => this.translations[lng]); } - - /** - * Substitutes text in a translation. - * If a translation is passed, it'll be fused - * - * // Should replace simple keys - * new Translation({"en": "Some text {key}"}).Subs({key: "xyz"}).textFor("en") // => "Some text xyz" - * - * // Should fuse translations - * const subpart = new Translation({"en": "subpart","nl":"onderdeel"}) - * const tr = new Translation({"en": "Full sentence with {part}", nl: "Volledige zin met {part}"}) - * const subbed = tr.Subs({part: subpart}) - * subbed.textFor("en") // => "Full sentence with subpart" - * subbed.textFor("nl") // => "Volledige zin met onderdeel" - */ - public Subs(text: any, context?: string): Translation { - return this.OnEveryLanguage((template, lang) => Utils.SubstituteKeys(template, text, lang), context) - } - + public OnEveryLanguage(f: (s: string, language: string) => string, context?: string): Translation { const newTranslations = {}; for (const lang in this.translations) { @@ -278,5 +257,28 @@ export class Translation extends BaseUIElement { return this.txt } +} +export class TypedTranslation extends Translation { + constructor(translations: object, context?: string) { + super(translations, context); + } + + /** + * Substitutes text in a translation. + * If a translation is passed, it'll be fused + * + * // Should replace simple keys + * new TypedTranslation({"en": "Some text {key}"}).Subs({key: "xyz"}).textFor("en") // => "Some text xyz" + * + * // Should fuse translations + * const subpart = new Translation({"en": "subpart","nl":"onderdeel"}) + * const tr = new TypedTranslation({"en": "Full sentence with {part}", nl: "Volledige zin met {part}"}) + * const subbed = tr.Subs({part: subpart}) + * subbed.textFor("en") // => "Full sentence with subpart" + * subbed.textFor("nl") // => "Volledige zin met onderdeel" + */ + Subs(text: T, context?: string): Translation { + return this.OnEveryLanguage((template, lang) => Utils.SubstituteKeys(template, text, lang), context) + } } \ No newline at end of file diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts index 482cc7eeb..6a817de9a 100644 --- a/UI/i18n/Translations.ts +++ b/UI/i18n/Translations.ts @@ -1,5 +1,5 @@ import {FixedUiElement} from "../Base/FixedUiElement"; -import {Translation} from "./Translation"; +import {Translation, TypedTranslation} from "./Translation"; import BaseUIElement from "../BaseUIElement"; import * as known_languages from "../../assets/generated/used_languages.json" import CompiledTranslations from "../../assets/generated/CompiledTranslations"; @@ -22,7 +22,26 @@ export default class Translations { return s; } - static T(t: string | any, context = undefined): Translation { + /** + * Converts a string or an object into a typed translation. + * Translation objects ('Translation' and 'TypedTranslation') are converted/returned + * + * Translations.T("some text") // => new TypedTranslation({"*": "some text"}) + * Translations.T("some text").txt // => "some text" + * + * const t = new Translation({"nl": "vertaling", "en": "translation"}) + * Translations.T(t) // => new TypedTranslation({"nl": "vertaling", "en": "translation"}) + * + * const t = new TypedTranslation({"nl": "vertaling", "en": "translation"}) + * Translations.T(t) // => t + * + * const json: any = {"en": "English", "nl": "Nederlands"}; + * const translation = Translations.T(new Translation(json)); + * translation.textFor("en") // => "English" + * translation.textFor("nl") // => "Nederlands" + * + */ + static T(t: string | any, context = undefined): TypedTranslation { if (t === undefined || t === null) { return undefined; } @@ -30,40 +49,22 @@ export default class Translations { t = "" + t } if (typeof t === "string") { - return new Translation({"*": t}, context); + return new TypedTranslation({"*": t}, context); } if (t.render !== undefined) { const msg = "Creating a translation, but this object contains a 'render'-field. Use the translation directly" console.error(msg, t); throw msg } - if (t instanceof Translation) { + if (t instanceof TypedTranslation) { return t; } - return new Translation(t, context); + if(t instanceof Translation){ + return new TypedTranslation(t.translations) + } + return new TypedTranslation(t, context); } - /** - * 'Wrap Translation': given an object containing translations OR a string, returns a translation object - * - * const json: any = {"en": "English", "nl": "Nederlands"}; - * const translation = Translations.WT(new Translation(json)); - * translation.textFor("en") // => "English" - * translation.textFor("nl") // => "Nederlands" - */ - public static WT(s: string | Translation): Translation { - if (s === undefined || s === null) { - return undefined; - } - if (typeof (s) === "string") { - return new Translation({'*': s}); - } - if (s instanceof Translation) { - return s.Clone() /* MUST CLONE HERE! */; - } - console.error("Trying to Translation.WT, but got ", s) - throw "??? Not a valid translation" - } public static CountTranslations() { const queue: any = [Translations.t]; diff --git a/Utils.ts b/Utils.ts index 7ee06e174..b55b4d775 100644 --- a/Utils.ts +++ b/Utils.ts @@ -518,11 +518,35 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be * Apply a function on every leaf of the JSON; used to rewrite parts of the JSON. * Returns a modified copy of the original object. * + * 'null' and 'undefined' are _always_ considered a leaf, even if 'isLeaf' says it isn't + * * Hangs if the object contains a loop + * + * // should walk a json + * const walked = Utils.WalkJson({ + * key: "value" + * }, (x: string) => x + "!") + * walked // => {key: "value!"} + * + * // should preserve undefined and null: + * const walked = Utils.WalkJson({ + * u: undefined, + * n: null, + * v: "value" + * }, (x) => {if(x !== undefined && x !== null){return x+"!}; return x}) + * walked // => {v: "value!", u: undefined, n: null} + * + * // should preserve undefined and null, also with a negative isLeaf: + * const walked = Utils.WalkJson({ + * u: undefined, + * n: null, + * v: "value" + * }, (x) => return x}, _ => false) + * walked // => {v: "value", u: undefined, n: null} */ static WalkJson(json: any, f: (v: object | number | string | boolean | undefined, path: string[]) => any, isLeaf: (object) => boolean = undefined, path: string[] = []) { - if (json === undefined) { - return f(undefined, path) + if (json === undefined || json === null) { + return f(json, path) } const jtp = typeof json if (isLeaf !== undefined) { @@ -732,7 +756,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be * Triggers a 'download file' popup which will download the contents */ public static offerContentsAsDownloadableFile(contents: string | Blob, fileName: string = "download.txt", - options?: { mimetype: string | "text/plain" | "text/csv" | "application/vnd.geo+json" | "{gpx=application/gpx+xml}" }) { + options?: { mimetype: string | "text/plain" | "text/csv" | "application/vnd.geo+json" | "{gpx=application/gpx+xml}" | "application/json" }) { const element = document.createElement("a"); let file; if (typeof (contents) === "string") { diff --git a/assets/contributors.json b/assets/contributors.json index ec40462fc..0d556c9cf 100644 --- a/assets/contributors.json +++ b/assets/contributors.json @@ -1,7 +1,7 @@ { "contributors": [ { - "commits": 3508, + "commits": 3540, "contributor": "Pieter Vander Vennet" }, { @@ -17,7 +17,7 @@ "contributor": "Christian Neumann" }, { - "commits": 31, + "commits": 32, "contributor": "Win Olario" }, { diff --git a/assets/language_native.json b/assets/language_native.json index 819cc1678..c81c79d34 100644 --- a/assets/language_native.json +++ b/assets/language_native.json @@ -1,22 +1,23 @@ { "ca": "català", "de": "Deutsch", - "eo": "Esperanto", - "fr": "français", - "es": "español", - "gl": "lingua galega", - "fi": "suomi", "en": "English", - "ru": "русский язык", - "it": "italiano", - "pl": "język polski", - "ja": "日本語", - "sv": "svenska", - "pt": "português", - "nl": "Nederlands", - "id": "Indonesia", + "eo": "Esperanto", + "es": "español", + "fi": "suomi", + "fr": "français", + "gl": "lingua galega", "hu": "magyar", + "id": "Indonesia", + "it": "italiano", + "ja": "日本語", "nb_NO": "bokmål", - "zh_Hant": "簡體中文", - "pt_BR": "português brasileiro" + "nl": "Nederlands", + "pl": "język polski", + "pt": "português", + "pt_BR": "português brasileiro", + "ru": "русский язык", + "sl": "slovenščina", + "sv": "svenska", + "zh_Hant": "簡體中文" } \ No newline at end of file diff --git a/assets/language_translations.json b/assets/language_translations.json index 383397e1d..2582af26e 100644 --- a/assets/language_translations.json +++ b/assets/language_translations.json @@ -1,27 +1,4 @@ { - "ca": { - "en": "Catalan", - "de": "Katalanisch", - "nl": "Catalaans", - "ca": "català", - "es": "catalán", - "fr": "catalan", - "eo": "kataluna lingvo", - "fi": "katalaani", - "gl": "lingua catalá", - "hu": "katalán", - "id": "Bahasa Katala", - "it": "catalano", - "ja": "カタルーニャ語", - "nb_NO": "katalansk", - "pl": "język kataloński", - "pt": "língua catalã", - "pt_BR": "língua catalã", - "ru": "каталанский язык", - "sv": "katalanska", - "zh_Hans": "加泰罗尼亚语", - "zh_Hant": "加泰隆尼亞語" - }, "de": { "ca": "alemany", "en": "German", @@ -41,6 +18,7 @@ "pl": "język niemiecki", "pt": "alemão", "ru": "немецкий язык", + "sl": "nemščina", "sv": "tyska", "zh_Hans": "德语", "zh_Hant": "德語" @@ -65,10 +43,36 @@ "pt": "esperanto", "pt_BR": "esperanto", "ru": "эсперанто", + "sl": "esperanto", "sv": "esperanto", "zh_Hans": "世界语" }, + "ca": { + "en": "Catalan", + "de": "Katalanisch", + "nl": "Catalaans", + "ca": "català", + "es": "catalán", + "fr": "catalan", + "eo": "kataluna lingvo", + "fi": "katalaani", + "gl": "lingua catalá", + "hu": "katalán", + "id": "Bahasa Katala", + "it": "catalano", + "ja": "カタルーニャ語", + "nb_NO": "katalansk", + "pl": "język kataloński", + "pt": "língua catalã", + "pt_BR": "língua catalã", + "ru": "каталанский язык", + "sl": "Katalonščina", + "sv": "katalanska", + "zh_Hans": "加泰罗尼亚语", + "zh_Hant": "加泰隆尼亞語" + }, "fr": { + "zh_Hans": "法语", "es": "francés", "nl": "Frans", "en": "French", @@ -84,11 +88,11 @@ "fi": "ranska", "gl": "lingua francesa", "ja": "フランス語", - "zh_Hans": "法语", "nb_NO": "fransk", "pl": "język francuski", "pt_BR": "francês", "ru": "французский язык", + "sl": "francoščina", "sv": "franska" }, "es": { @@ -110,6 +114,7 @@ "pt": "espanhol", "pt_BR": "espanhol", "ru": "испанский язык", + "sl": "španščina", "sv": "spanska", "zh_Hans": "西班牙语", "zh_Hant": "西班牙語" @@ -133,17 +138,11 @@ "pt": "galego", "pt_BR": "língua galega", "ru": "галисийский язык", + "sl": "Galicijščina", "sv": "galiciska", "zh_Hant": "加利西亞語" }, "fi": { - "nb_NO": "finsk", - "pl": "język fiński", - "pt": "finlandês", - "pt_BR": "língua finlandesa", - "sv": "finska", - "zh_Hans": "芬兰语", - "zh_Hant": "芬蘭語", "nl": "Fins", "de": "Finnisch", "en": "Finnish", @@ -157,16 +156,17 @@ "ca": "finès", "eo": "finna lingvo", "fr": "finnois", - "gl": "finés" + "gl": "finés", + "nb_NO": "finsk", + "pl": "język fiński", + "pt": "finlandês", + "pt_BR": "língua finlandesa", + "sl": "finščina", + "sv": "finska", + "zh_Hans": "芬兰语", + "zh_Hant": "芬蘭語" }, "en": { - "pl": "język angielski", - "pt": "inglês", - "pt_BR": "inglês", - "ru": "английский язык", - "sv": "engelska", - "zh_Hans": "英语", - "zh_Hant": "英語", "id": "Inggris", "it": "inglese", "ja": "英語", @@ -180,9 +180,25 @@ "fi": "englanti", "fr": "anglais", "gl": "lingua inglesa", - "hu": "angol" + "hu": "angol", + "pl": "język angielski", + "pt": "inglês", + "pt_BR": "inglês", + "ru": "английский язык", + "sl": "angleščina", + "sv": "engelska", + "zh_Hans": "英语", + "zh_Hant": "英語" }, "ru": { + "zh_Hans": "俄语", + "zh_Hant": "俄語", + "hu": "orosz", + "en": "Russian", + "ru": "русский язык", + "es": "ruso", + "fr": "russe", + "nl": "Russisch", "ca": "rus", "de": "Russisch", "eo": "rusa lingvo", @@ -191,88 +207,35 @@ "id": "Rusia", "it": "russo", "ja": "ロシア語", - "hu": "orosz", - "en": "Russian", - "ru": "русский язык", - "es": "ruso", - "fr": "russe", - "nl": "Russisch", - "sv": "ryska", - "zh_Hans": "俄语", - "zh_Hant": "俄語", "nb_NO": "russisk", "pl": "język rosyjski", "pt": "russo", - "pt_BR": "russo" + "pt_BR": "russo", + "sl": "ruščina", + "sv": "ryska" }, - "it": { - "zh_Hans": "意大利语", - "zh_Hant": "義大利語", - "nb_NO": "italiensk", - "pl": "język włoski", - "pt_BR": "língua italiana", - "ru": "итальянский язык", - "sv": "italienska", - "ca": "italià", - "eo": "itala lingvo", - "fi": "italia", - "gl": "lingua italiana", - "en": "Italian", - "ja": "イタリア語", - "es": "italiano", - "hu": "olasz", - "id": "Italia", - "it": "italiano", - "fr": "italien", - "de": "Italienisch", - "nl": "Italiaans", - "pt": "italiano" - }, - "pl": { - "de": "Polnisch", - "en": "Polish", - "pl": "język polski", - "es": "polaco", - "fr": "polonais", - "ca": "polonès", - "eo": "pola lingvo", - "fi": "puola", - "gl": "lingua polaca", - "hu": "lengyel", - "id": "Polandia", - "zh_Hans": "波兰语", - "zh_Hant": "波蘭語", - "it": "polacco", - "ja": "ポーランド語", - "nb_NO": "polsk", - "nl": "Pools", - "pt": "polaco", - "pt_BR": "língua polonesa", - "ru": "польский язык", - "sv": "polska" - }, - "ja": { - "nb_NO": "japansk", - "nl": "Japans", - "pl": "język japoński", - "pt": "japonês", - "pt_BR": "língua japonesa", - "ru": "японский язык", - "sv": "japanska", - "zh_Hans": "日语", - "zh_Hant": "日語", - "en": "Japanese", - "ca": "japonès", - "de": "Japanisch", - "eo": "japana lingvo", - "es": "japonés", - "fi": "japani", - "fr": "japonais", - "gl": "lingua xaponesa", - "hu": "japán", - "id": "Bahasa Jepang", - "it": "giapponese", - "ja": "日本語" + "sl": { + "en": "Slovene", + "ca": "eslovè", + "de": "Slowenisch", + "eo": "slovena lingvo", + "es": "esloveno", + "fi": "sloveeni", + "fr": "slovène", + "gl": "lingua eslovena", + "hu": "szlovén", + "id": "Bahasa Slovenia", + "it": "sloveno", + "ja": "スロベニア語", + "nb_NO": "slovensk", + "nl": "Sloveens", + "pl": "język słoweński", + "pt": "língua eslovena", + "pt_BR": "língua eslovena", + "ru": "словенский язык", + "sl": "slovenščina", + "sv": "slovenska", + "zh_Hant": "斯洛維尼亞語" }, "sv": { "en": "Swedish", @@ -294,8 +257,33 @@ "pt": "língua sueca", "pt_BR": "língua sueca", "ru": "шведский язык", + "sl": "švedščina", "zh_Hant": "瑞典語" }, + "it": { + "en": "Italian", + "ja": "イタリア語", + "es": "italiano", + "hu": "olasz", + "id": "Italia", + "it": "italiano", + "fr": "italien", + "de": "Italienisch", + "nl": "Italiaans", + "pt": "italiano", + "ca": "italià", + "eo": "itala lingvo", + "fi": "italia", + "gl": "lingua italiana", + "nb_NO": "italiensk", + "pl": "język włoski", + "pt_BR": "língua italiana", + "ru": "итальянский язык", + "sl": "italijanščina", + "sv": "italienska", + "zh_Hans": "意大利语", + "zh_Hant": "義大利語" + }, "pt": { "en": "Portuguese", "hu": "portugál", @@ -315,32 +303,105 @@ "pl": "język portugalski", "pt_BR": "português", "ru": "португальский язык", + "sl": "portugalščina", "sv": "portugisiska", "zh_Hans": "葡萄牙语", "zh_Hant": "葡萄牙語" }, + "pl": { + "de": "Polnisch", + "en": "Polish", + "pl": "język polski", + "es": "polaco", + "fr": "polonais", + "nb_NO": "polsk", + "nl": "Pools", + "pt": "polaco", + "pt_BR": "língua polonesa", + "ru": "польский язык", + "sl": "poljščina", + "sv": "polska", + "zh_Hans": "波兰语", + "zh_Hant": "波蘭語", + "ca": "polonès", + "eo": "pola lingvo", + "fi": "puola", + "gl": "lingua polaca", + "hu": "lengyel", + "id": "Polandia", + "it": "polacco", + "ja": "ポーランド語" + }, + "ja": { + "nb_NO": "japansk", + "nl": "Japans", + "pl": "język japoński", + "pt": "japonês", + "pt_BR": "língua japonesa", + "ru": "японский язык", + "sl": "Japonščina", + "sv": "japanska", + "zh_Hans": "日语", + "zh_Hant": "日語", + "id": "bahasa Jepang", + "en": "Japanese", + "ca": "japonès", + "de": "Japanisch", + "eo": "japana lingvo", + "es": "japonés", + "fi": "japani", + "fr": "japonais", + "gl": "lingua xaponesa", + "hu": "japán", + "it": "giapponese", + "ja": "日本語" + }, "nl": { "en": "Dutch", "de": "Niederländisch", "nl": "Nederlands", "ca": "neerlandès", - "es": "neerlandés", "fr": "néerlandais", "hu": "holland", "id": "Belanda", "it": "olandese", + "es": "Neerlandés", "eo": "nederlanda lingvo", "fi": "hollanti", "gl": "lingua neerlandesa", - "zh_Hans": "荷兰语", - "zh_Hant": "荷蘭語", "ja": "オランダ語", "nb_NO": "nederlandsk", "pl": "język niderlandzki", "pt": "neerlandês", "pt_BR": "neerlandês", "ru": "нидерландский язык", - "sv": "nederländska" + "sl": "Nizozemščina", + "sv": "nederländska", + "zh_Hans": "荷兰语", + "zh_Hant": "荷蘭語" + }, + "hu": { + "en": "Hungarian", + "fr": "hongrois", + "pt": "húngaro", + "pt_BR": "língua húngara", + "ru": "венгерский язык", + "sl": "madžarščina", + "sv": "ungerska", + "zh_Hant": "匈牙利語", + "ca": "hongarès", + "de": "Ungarisch", + "eo": "hungara lingvo", + "es": "húngaro", + "fi": "unkari", + "gl": "lingua húngara", + "hu": "magyar", + "id": "Hongaria", + "it": "ungherese", + "ja": "ハンガリー語", + "nb_NO": "ungarsk", + "nl": "Hongaars", + "pl": "język węgierski" }, "id": { "en": "Indonesian", @@ -361,33 +422,16 @@ "pt": "língua indonésia", "pt_BR": "língua indonésia", "ru": "индонезийский язык", + "sl": "indonezijščina", "sv": "indonesiska", "zh_Hans": "印度尼西亚语", "zh_Hant": "印尼語" }, - "hu": { - "nb_NO": "ungarsk", - "nl": "Hongaars", - "pl": "język węgierski", - "pt": "húngaro", - "pt_BR": "língua húngara", - "ru": "венгерский язык", - "sv": "ungerska", - "zh_Hant": "匈牙利語", - "ca": "hongarès", - "de": "Ungarisch", - "eo": "hungara lingvo", - "es": "húngaro", - "fi": "unkari", - "gl": "lingua húngara", - "hu": "magyar", - "id": "Hongaria", - "it": "ungherese", - "ja": "ハンガリー語", - "en": "Hungarian", - "fr": "hongrois" - }, "nb_NO": { + "ca": "bokmål", + "de": "Bokmål", + "en": "Bokmål", + "eo": "Bokmål", "es": "bokmål", "fi": "kirjanorja", "fr": "bokmål", @@ -402,11 +446,8 @@ "pt": "bokmål", "pt_BR": "Bokmål", "ru": "букмол", - "sv": "bokmål", - "ca": "bokmål", - "de": "Bokmål", - "en": "Bokmål", - "eo": "Bokmål" + "sl": "Bokmål", + "sv": "bokmål" }, "zh_Hant": { "ca": "xinès simplificat", @@ -420,7 +461,7 @@ "it": "cinese semplificato", "ja": "簡体字中国語", "nb_NO": "tradisjonell kinesisk", - "pl": "Chiński uproszczony", + "pl": "język chiński uproszczony", "pt": "chinês simplificado", "zh_Hans": "简体中文", "zh_Hant": "簡體中文", diff --git a/assets/layers/address/address.json b/assets/layers/address/address.json index aee9af093..506d931ae 100644 --- a/assets/layers/address/address.json +++ b/assets/layers/address/address.json @@ -10,7 +10,8 @@ "ru": "Известные адреса в OSM", "id": "Alamat yang dikenal di OSM", "es": "Direcciones conocidas en OSM", - "zh_Hans": "OSM中已知的地址" + "zh_Hans": "OSM中已知的地址", + "nb_NO": "Kjente adresser i OSM" }, "minzoom": 18, "source": { @@ -38,7 +39,8 @@ "ru": "Известный адрес", "es": "Domicilio conocido", "zh_Hans": "已知的地址", - "id": "Alamat yang diketahui" + "id": "Alamat yang diketahui", + "nb_NO": "Kjent adresse" } }, "description": { @@ -52,7 +54,9 @@ "pl": "Adresy", "id": "Alamat", "es": "Direcciones", - "zh_Hans": "地址" + "zh_Hans": "地址", + "ca": "Adreces", + "nb_NO": "Adresser" }, "tagRenderings": [ { @@ -66,7 +70,8 @@ "pl": "Numer tego domu to {addr:housenumber}", "ru": "Номер дома {addr:housenumber}", "zh_Hans": "门牌号是{addr:housenumber}", - "id": "Nomor rumah ini {addr:housenumber}" + "id": "Nomor rumah ini {addr:housenumber}", + "es": "La numeración de la casa es {addr:housenumber}" }, "question": { "en": "What is the number of this house?", @@ -118,7 +123,8 @@ "fr": "Le nom de la voie est {addr:street}", "pl": "Ten adres znajduje się na ulicy {addr:street}", "zh_Hans": "这个地址位于{addr:street}街", - "id": "Alamat ini ada di jalan {addr:street}" + "id": "Alamat ini ada di jalan {addr:street}", + "es": "La dirección está en la calle {addr:street}" }, "question": { "en": "What street is this address located in?", diff --git a/assets/layers/ambulancestation/ambulancestation.json b/assets/layers/ambulancestation/ambulancestation.json index 8e4a199dd..039c37c1f 100644 --- a/assets/layers/ambulancestation/ambulancestation.json +++ b/assets/layers/ambulancestation/ambulancestation.json @@ -10,7 +10,8 @@ "hu": "Mentőállomás-térkép", "nl": "Kaart van ambulancestations", "zh_Hans": "救护车站地图", - "id": "Peta stasiun ambulans" + "id": "Peta stasiun ambulans", + "es": "Mapa de estaciones de ambulancias" }, "minzoom": 12, "source": { @@ -29,7 +30,8 @@ "de": "Rettungswache", "it": "Stazione delle ambulanze", "hu": "Mentőállomás", - "nl": "Ambulancestation" + "nl": "Ambulancestation", + "es": "Estación de Ambulancias" } }, "description": { @@ -40,7 +42,8 @@ "it": "La stazione delle ambulanze è un’area per lo stoccaggio delle ambulanze, dell’equipaggiamento medico, dei dispositivi di protezione individuale e di altre forniture medicali.", "hu": "A mentőállomás olyan terület, ahol mentőautókat, orvosi felszereléseket, egyéni védőfelszereléseket és egyéb orvosi felszereléseket tárolnak.", "ru": "Станция скорой помощи это полигон для хранения транспорта, медицинского оборудования, средств индивидуальной защиты и других медицинских принадлежностей.", - "nl": "Een ambulancestation is een plaats waar ambulances, medisch materiaal, persoonlijk beschermingsmateriaal en aanverwanten worden bewaard." + "nl": "Een ambulancestation is een plaats waar ambulances, medisch materiaal, persoonlijk beschermingsmateriaal en aanverwanten worden bewaard.", + "es": "Una estación de ambulancias es una zona para almacenar vehículos de ambulancia, equipamiento médico, equipos de protección personal y otros suministros médicos." }, "tagRenderings": [ { @@ -56,7 +59,9 @@ "it": "Qual è il nome di questa stazione delle ambulanze?", "de": "Wie heißt diese Rettungswache?", "hu": "Mi a neve ennek a menőtállomásnak?", - "nl": "Hoe heet dit ambulancestation?" + "nl": "Hoe heet dit ambulancestation?", + "es": "¿Cual es el nombre de esta estación de ambulancias?", + "nb_NO": "Hva er navnet på denne ambulansestasjonen?" }, "render": { "en": "This station is called {name}.", @@ -66,7 +71,9 @@ "it": "Questa stazione è chiamata {name}.", "de": "Diese Rettungswache heißt {name}.", "hu": "A mentőállomás neve: {name}.", - "nl": "Dit station heet {name}." + "nl": "Dit station heet {name}.", + "es": "Esta estación se llama {name}.", + "nb_NO": "Denne stasjonen heter {name}." } }, { @@ -82,7 +89,8 @@ "it": " Come si chiama la strada in cui si trova questa stazione?", "de": " Wie lautet der Name der Straße, in der sich die Rettungswache befindet?", "hu": " Mi a neve annak az utcának, amelyben az állomás található?", - "nl": " In welke straat ligt dit station?" + "nl": " In welke straat ligt dit station?", + "es": " ¿Cual es el nombre de la calle en la que se encuentra la estación?" }, "render": { "en": "This station is along a highway called {addr:street}.", @@ -92,7 +100,8 @@ "it": "Questa stazione si trova in {addr:street}.", "de": "Dieser Bahnhof liegt an der Straße {addr:street}.", "hu": "Ez az állomás a következő utcában van: {addr:street}.", - "nl": "Straat waar dit station ligt: {addr:street}" + "nl": "Straat waar dit station ligt: {addr:street}", + "es": "Esta estación se encuentra al lado de una autovía llamada {addr:street}." } }, { @@ -105,7 +114,8 @@ "it": "Dove si trova la stazione? (ad es. quartiere, paese o città)", "de": "Wo befindet sich die Rettungswache? (z. B. Name von Stadtviertel, Dorf oder Stadt)", "hu": "Hol található az állomás? (Pl. a falu, kisváros vagy városrész neve.)", - "nl": "Waar ligt het station? (v.b. naam van de buurt, dorp of stad)" + "nl": "Waar ligt het station? (v.b. naam van de buurt, dorp of stad)", + "es": "¿Dónde se encuentra la estación? (ej. nombre del barrio, pueblo o ciudad)" }, "freeform": { "key": "addr:place" @@ -117,7 +127,8 @@ "it": "La stazione si trova a {addr:place}.", "de": "Diese Rettungswache befindet sich in {addr:place}.", "hu": "Ez az állomás itt található: {addr:place}.", - "nl": "Dit station ligt in {addr:place}." + "nl": "Dit station ligt in {addr:place}.", + "es": "Esta estación se encuentra en {addr:place}." } }, { @@ -130,7 +141,8 @@ "de": "Welches Unternehmen betreibt diese Rettungswache?", "hu": "Milyen szervezet működteti ezt az állomást?", "ru": "Какая организация управляет этой станцией?", - "nl": "Welke organisatie beheert dit station?" + "nl": "Welke organisatie beheert dit station?", + "es": "¿Qué agencia opera esta estación?" }, "render": { "en": "This station is operated by {operator}.", @@ -140,7 +152,8 @@ "de": "Diese Rettungswache wird betrieben von {operator}.", "hu": "Az állomás üzemeltetője: {operator}.", "ru": "Эта станция управляется {operator}.", - "nl": "Dit station wordt beheerd door {operator}." + "nl": "Dit station wordt beheerd door {operator}.", + "es": "Esta estación la opera {operator}." }, "freeform": { "key": "operator" @@ -156,7 +169,8 @@ "it": "Com’è classificato il gestore della stazione?", "de": "Wie kann der Betreiber der Rettungswache eingestuft werden?", "hu": "Hogyan sorolható be az állomás üzemeltetője?", - "nl": "Wat voor een organisatie is de beheerder van dit station?" + "nl": "Wat voor een organisatie is de beheerder van dit station?", + "es": "¿Como está clasificada la operadora de la estación?" }, "render": { "en": "The operator is a(n) {operator:type} entity.", @@ -165,7 +179,8 @@ "it": "L’operatore è un ente {operator:type}.", "de": "Der Betreiber ist eine {operator:type}.", "hu": "Az üzemeltető egy {operator:type} jellegű szervezet.", - "nl": "De beheerder is van het type {operator:type}." + "nl": "De beheerder is van het type {operator:type}.", + "es": "La operador a no es una entidad de tipo {operator:type}." }, "freeform": { "key": "operator:type" @@ -185,7 +200,8 @@ "de": "Die Rettungswache wird von einer Behörde betrieben.", "hu": "A mentőállomást a kormány üzemelteti.", "ru": "Станция управляется правительством.", - "nl": "Dit station wordt beheerd door de overheid." + "nl": "Dit station wordt beheerd door de overheid.", + "es": "La estación la opera el govierno." } }, { @@ -202,7 +218,8 @@ "de": "Die Rettungswache wird von einer gemeindenahen oder informellen Organisation betrieben.", "hu": "Mentőállomást egy közösségi vagy nem hivatalos szervezet működteti.", "ru": "Станция управляется волонтёрами или частной организацией.", - "nl": "Dit station wordt beheerd door een informele of community organisatie." + "nl": "Dit station wordt beheerd door een informele of community organisatie.", + "es": "La estación la opera una organización basada en la comunidad o informal." } }, { @@ -218,7 +235,8 @@ "it": "La stazione è gestita da un gruppo ufficiale di volontari.", "de": "Die Rettungswache wird von einer Freiwilligenorganisation betrieben.", "hu": "A mentőállomást egy önkéntesekből álló hivatalos csoport működteti.", - "nl": "Dit station wordt beheerd door een formele groep vrijwilligers." + "nl": "Dit station wordt beheerd door een formele groep vrijwilligers.", + "es": "La estación la opera un grupo formal de voluntarios." } }, { @@ -234,7 +252,8 @@ "it": "La stazione è gestita da un privato.", "de": "Die Rettungswache wird von einer privaten Organisation betrieben.", "hu": "Az állomást egy magánkézben lévő szervezet működteti.", - "nl": "Dit station wordt beheerd door een privé-organisatie." + "nl": "Dit station wordt beheerd door een privé-organisatie.", + "es": "La estación es de gestión privada." } } ] @@ -256,7 +275,9 @@ "hu": "Mentőállomás", "nl": "een ambulancestation", "zh_Hans": "救护车站", - "id": "Stasiun ambulans" + "id": "Stasiun ambulans", + "es": "una estación de ambulancias", + "nb_NO": "en ambulansestasjon" }, "description": { "en": "Add an ambulance station to the map", @@ -268,7 +289,9 @@ "hu": "Mentőállomás hozzáadása a térképhez", "nl": "Voeg een ambulancestation toe aan de kaart", "zh_Hans": "向地图中添加一个救护车站", - "id": "Tambahkan stasiun ambulans ke peta" + "id": "Tambahkan stasiun ambulans ke peta", + "es": "Añadir una estación de ambulancias al mapa", + "nb_NO": "Legg til en ambulansestasjon på kartet" } } ], diff --git a/assets/layers/artwork/artwork.json b/assets/layers/artwork/artwork.json index 88bfa5dc1..f433e7f5c 100644 --- a/assets/layers/artwork/artwork.json +++ b/assets/layers/artwork/artwork.json @@ -14,7 +14,8 @@ "nb_NO": "Kunstverk", "pt": "Obras de arte", "hu": "Műalkotások", - "pl": "Dzieła sztuki" + "pl": "Dzieła sztuki", + "ca": "Obres d'art" }, "source": { "osmTags": "tourism=artwork" @@ -38,7 +39,8 @@ "pl": "Dzieło sztuki", "pt": "Obra de arte", "pt_BR": "Obra de arte", - "sv": "Konstverk" + "sv": "Konstverk", + "ca": "Obra d'art" }, "mappings": [ { @@ -166,7 +168,8 @@ "pt": "Arquitetura", "hu": "Építészet", "pl": "Architektura", - "es": "Arquitectura" + "es": "Arquitectura", + "ca": "Arquitectura" } }, { @@ -185,7 +188,8 @@ "pt": "Mural", "hu": "Falfestmény", "pl": "Mural", - "es": "Mural" + "es": "Mural", + "ca": "Mural" } }, { @@ -204,7 +208,8 @@ "pt": "Pintura", "hu": "Festmény", "pl": "Obraz", - "es": "Pintura" + "es": "Pintura", + "ca": "Pintura" } }, { @@ -223,7 +228,8 @@ "pt": "Escultura", "hu": "Absztrakt szobor", "pl": "Rzeźba", - "es": "Escultura" + "es": "Escultura", + "ca": "Escultura" } }, { @@ -241,7 +247,8 @@ "pt": "Estátua", "hu": "Szobor", "pl": "Posąg", - "es": "Estatua" + "es": "Estatua", + "ca": "Estàtua" } }, { @@ -259,7 +266,8 @@ "pt": "Busto", "hu": "Mellszobor", "pl": "Popiersie", - "es": "Busto" + "es": "Busto", + "ca": "Bust" } }, { @@ -277,7 +285,9 @@ "id": "Batu", "pt": "Pedra", "hu": "Kő", - "pl": "Skała" + "pl": "Skała", + "ca": "Pedra", + "es": "Piedra" } }, { @@ -296,7 +306,8 @@ "pt": "Instalação", "hu": "Installáció", "pl": "Instalacja artystyczna", - "es": "Instalación" + "es": "Instalación", + "ca": "Instal·lació" } }, { @@ -315,7 +326,8 @@ "pt": "Graffiti", "hu": "Graffiti", "pl": "Graffiti", - "es": "Grafiti" + "es": "Grafiti", + "ca": "Grafiti" } }, { @@ -333,7 +345,9 @@ "id": "Relief", "pt": "Relevo", "hu": "Dombormű", - "pl": "Płaskorzeźba" + "pl": "Płaskorzeźba", + "ca": "Relleu", + "es": "Relieve" } }, { @@ -351,7 +365,8 @@ "id": "Azulejo (ubin dekoratif Spanyol)", "pt": "Azulejo (azulejo decorativo espanhol e português)", "hu": "Azulejo (portugál vagy spanyol dekoratív csempe)", - "pl": "Azulejo (hiszpańskie płytka dekoracyjna)" + "pl": "Azulejo (hiszpańskie płytka dekoracyjna)", + "es": "Azulejo (azulejos decorativos españoles)" } }, { @@ -368,7 +383,9 @@ "nb_NO": "Flisarbeid", "pt": "Ladrilhos", "hu": "Csempe", - "pl": "Płyta ceramiczna (fliza)" + "pl": "Płyta ceramiczna (fliza)", + "ca": "Enrajolat", + "es": "Cerámica" } } ], @@ -388,7 +405,8 @@ "id": "Seniman mana yang menciptakan ini?", "pt": "Que artista criou isto?", "hu": "Melyik művész alkotása ezt?", - "pl": "Który artysta to stworzył?" + "pl": "Który artysta to stworzył?", + "es": "¿Que artista creó esto?" }, "render": { "en": "Created by {artist_name}", @@ -403,7 +421,8 @@ "id": "Dibuat oleh {artist_name}", "pt": "Criado por {artist_name}", "hu": "Alkotó: {artist_name}", - "pl": "Stworzone przez {artist_name}" + "pl": "Stworzone przez {artist_name}", + "es": "Creado por {artist_name}" }, "freeform": { "key": "artist_name" @@ -424,7 +443,8 @@ "id": "Adakah situs web mengenai informasi lebih lanjut tentang karya seni ini?", "pt": "Existe um site com mais informações sobre esta obra de arte?", "hu": "Van-e olyan honlap, amely további információkat tartalmaz erről a műalkotásról?", - "pl": "Gdzie znajdę więcej informacji na temat tego dzieła sztuki?" + "pl": "Gdzie znajdę więcej informacji na temat tego dzieła sztuki?", + "es": "¿Hay un sitio web con más información sobre esta obra de arte?" }, "render": { "en": "More information on this website", @@ -439,7 +459,8 @@ "nb_NO": "Mer info er å finne på denne nettsiden", "pt": "Mais informações neste site", "hu": "További információ ezen a weboldalon", - "pl": "Więcej informacji na tej stronie" + "pl": "Więcej informacji na tej stronie", + "es": "Más información en este sitio web" }, "freeform": { "key": "website", @@ -460,7 +481,8 @@ "nb_NO": "Hvilken Wikipedia-oppføring samsvarer med dette kunstverket?", "id": "Entri Wikidata mana yang sesuai dengan karya seni ini?", "pt": "Que entrada no Wikidata corresponde a esta obra de arte?", - "hu": "Melyik Wikidata-bejegyzés felel meg ennek a műalkotásnak?" + "hu": "Melyik Wikidata-bejegyzés felel meg ennek a műalkotásnak?", + "es": "¿Qué entrada de Wikidata se corresponde con esta obra de arte?" }, "render": { "en": "Corresponds with {wikidata}", @@ -474,7 +496,8 @@ "nb_NO": "Samsvarer med {wikidata}", "id": "Sesuai dengan {wikidata}", "pt": "Corresponde a {wikidata}", - "hu": "Ez a megfelelő: {wikidata}" + "hu": "Ez a megfelelő: {wikidata}", + "es": "Se corresponde con {wikidata}" }, "freeform": { "key": "wikidata", diff --git a/assets/layers/barrier/barrier.json b/assets/layers/barrier/barrier.json index 4e28cd479..c33186116 100644 --- a/assets/layers/barrier/barrier.json +++ b/assets/layers/barrier/barrier.json @@ -7,7 +7,8 @@ "ru": "Препятствия", "hu": "Akadályok", "fr": "Barrières", - "es": "Barreras" + "es": "Barreras", + "ca": "Barreres" }, "description": { "en": "Obstacles while cycling, such as bollards and cycle barriers", @@ -32,7 +33,8 @@ "de": "Hindernis", "ru": "Препятствие", "fr": "Barrière", - "es": "Barrera" + "es": "Barrera", + "ca": "Barrera" }, "mappings": [ { @@ -43,7 +45,8 @@ "de": "Poller", "ru": "Прикол", "fr": "Bollard", - "es": "Bolardo" + "es": "Bolardo", + "ca": "Pilona" } }, { @@ -52,7 +55,8 @@ "en": "Cycling Barrier", "nl": "Fietshekjes", "de": "Barriere für Radfahrer", - "fr": "Barrière cyclable" + "fr": "Barrière cyclable", + "ca": "Barrera ciclista" } } ] @@ -66,7 +70,8 @@ "ru": "Прикол", "fr": "une bollard", "hu": "Terelőoszlop", - "es": "una bolardo" + "es": "una bolardo", + "ca": "una pilona" }, "tags": [ "barrier=bollard" @@ -76,7 +81,8 @@ "nl": "Een paaltje in de weg", "de": "Ein Poller auf der Straße", "hu": "Terelőoszlop az úton", - "fr": "Un potelet sur le chemin" + "fr": "Un potelet sur le chemin", + "es": "Un bolardo en la carretera" }, "preciseInput": { "preferredBackground": [ @@ -155,7 +161,9 @@ "en": "This is a single bollard in the road", "hu": "Ez egyetlen oszlop az úton", "nl": "Dit is een enkel paaltje in de weg", - "fr": "C'est un plot unique sur la route" + "fr": "C'est un plot unique sur la route", + "de": "Dies ist ein einzelner Poller auf der Straße", + "es": "Este es un único bolardo en la carretera" } }, { @@ -164,7 +172,9 @@ "en": "This is a cycle barrier slowing down cyclists", "nl": "Dit zijn fietshekjes die fietsers afremmen", "hu": "Ez egy kerékpárakadály, amely lelassítja a kerékpárosokat", - "fr": "C'est une barrière visant à ralentir les vélos" + "fr": "C'est une barrière visant à ralentir les vélos", + "de": "Dies ist eine Fahrradbarriere, die Radfahrer abbremst", + "es": "Esta es una barrera ciclista que ralentiza a los ciclistas" } } ] @@ -187,7 +197,8 @@ "nl": "Verwijderbare paal", "de": "Entfernbarer Poller", "fr": "Bollard amovible", - "hu": "Eltávolítható terelőoszlop" + "hu": "Eltávolítható terelőoszlop", + "ca": "Pilona desmuntable" } }, { @@ -198,7 +209,8 @@ "de": "Feststehender Poller", "fr": "Bollard fixe", "hu": "Rögzített terelőoszlop", - "es": "Bolardo fijo" + "es": "Bolardo fijo", + "ca": "Pilona fixa" } }, { @@ -230,7 +242,8 @@ "de": "Ausfahrender Poller", "fr": "Bollard rétractable", "hu": "Felemelkedő terelőoszlop", - "es": "Bolardo levadizo" + "es": "Bolardo levadizo", + "ca": "Pilona retràctil" } } ], @@ -242,7 +255,8 @@ "nl": "Wat voor fietshekjes zijn dit?", "de": "Um welche Art Fahrradhindernis handelt es sich?", "hu": "Milyen fajta kerékpárakadály ez?", - "fr": "Quel est ce type de barrière cyclable ?" + "fr": "Quel est ce type de barrière cyclable ?", + "es": "¿Qué tipo de barrera ciclista es esta?" }, "condition": "barrier=cycle_barrier", "mappings": [ @@ -311,14 +325,16 @@ "nl": "Maximumbreedte: {maxwidth:physical} m", "de": "Maximale Durchfahrtsbreite: {maxwidth:physical} m", "fr": "Largeur maximale: {maxwidth:physical} m", - "hu": "Legnagyobb szélesség: {maxwidth:physical} m" + "hu": "Legnagyobb szélesség: {maxwidth:physical} m", + "es": "Anchura máxima: {maxwidth:physical} m" }, "question": { "en": "How wide is the gap left over besides the barrier?", "nl": "Hoe breed is de ruimte naast de barrière?", "de": "Welche Durchfahrtsbreite hat das Hindernis?", "hu": "Milyen széles az akadályon az a rés, amelyen át lehet haladni?", - "fr": "Quelle est la largeur du passage ?" + "fr": "Quelle est la largeur du passage ?", + "es": "¿Cómo de ancho es el hueco dejado fuera de la barrera?" }, "condition": { "and": [ @@ -342,14 +358,16 @@ "nl": "Ruimte tussen barrières (langs de lengte van de weg): {width:separation} m", "de": "Abstand zwischen den Barrieren (entlang der Straße): {width:separation} m", "hu": "A korlátok közötti távolság (az út irányában): {width:separation} m", - "fr": "Espace entre deux barrières successives : {width:separation} m" + "fr": "Espace entre deux barrières successives : {width:separation} m", + "es": "Espacio entre barreras (a lo largo de la longitud de la carretera): {width:separation} m" }, "question": { "en": "How much space is there between the barriers (along the length of the road)?", "nl": "Hoeveel ruimte is er tussen de barrières (langs de lengte van de weg)?", "de": "Wie groß ist der Abstand zwischen den Barrieren (entlang der Straße)?", "hu": "Mekkora távolság van a korlátok között (az út irányában)?", - "fr": "Combien d’espace sépare deux barrières successives ?" + "fr": "Combien d’espace sépare deux barrières successives ?", + "es": "¿Cuánto espacio hay entre las barreras (a lo largo de la longitud de la carretera)?" }, "condition": { "or": [ @@ -373,14 +391,16 @@ "nl": "Breedte van de opening: {width:opening} m", "de": "Breite der Öffnung: {width:opening} m", "fr": "Largeur de l'ouverture : {width:opening} m", - "hu": "Nyílás szélessége: {width:opening} m" + "hu": "Nyílás szélessége: {width:opening} m", + "es": "Anchura de la apertura: {width:opening} m" }, "question": { "en": "How wide is the smallest opening next to the barriers?", "nl": "Hoe breed is de smalste opening naast de barrières?", "de": "Wie breit ist die kleinste Öffnung neben den Barrieren?", "hu": "Milyen széles a korlátok melletti legkisebb nyílás?", - "fr": "Quelle est la largeur d'ouverture après la plus petite près de la barrière ?" + "fr": "Quelle est la largeur d'ouverture après la plus petite près de la barrière ?", + "es": "¿Cómo de año es la apertura más pequeña al lado de las barreras?" }, "condition": { "or": [ @@ -404,14 +424,16 @@ "de": "Überschneidung: {overlap} m", "hu": "Átfedés: {overlap} m", "fr": "Chevauchement : {overlap} m", - "nl": "Overlap: {overlap} m" + "nl": "Overlap: {overlap} m", + "es": "Solapado: {overlap} m" }, "question": { "en": "How much overlap do the barriers have?", "nl": "Hoeveel overlappen de barrières?", "de": "Wie stark überschneiden sich die Barrieren?", "hu": "Mekkora a korlátok átfedése?", - "fr": "Quel est le chevauchement des barrières ?" + "fr": "Quel est le chevauchement des barrières ?", + "es": "¿Cuánto se solapan las barreras?" }, "condition": { "or": [ diff --git a/assets/layers/bench/bench.json b/assets/layers/bench/bench.json index 85c30e2ed..b173ae7a6 100644 --- a/assets/layers/bench/bench.json +++ b/assets/layers/bench/bench.json @@ -16,7 +16,8 @@ "fi": "Penkit", "pl": "Ławki", "pt_BR": "Bancos", - "pt": "Bancos" + "pt": "Bancos", + "ca": "Bancs" }, "minzoom": 17, "source": { @@ -39,7 +40,8 @@ "fi": "Penkki", "pl": "Ławka", "pt_BR": "Banco", - "pt": "Banco" + "pt": "Banco", + "ca": "Banc" } }, "tagRenderings": [ @@ -64,7 +66,8 @@ "fi": "Selkänoja: kyllä", "pl": "Oparcie: Tak", "pt_BR": "Encosto: Sim", - "pt": "Encosto: Sim" + "pt": "Encosto: Sim", + "ca": "Respatller: sí" } }, { @@ -85,7 +88,8 @@ "fi": "Selkänoja: ei", "pl": "Oparcie: Nie", "pt_BR": "Encosto: Não", - "pt": "Encosto: Não" + "pt": "Encosto: Não", + "ca": "Respatller: No" } } ], @@ -123,7 +127,8 @@ "nb_NO": "{seats} seter", "pl": "{seats} siedzeń", "pt_BR": "{seats} assentos", - "pt": "{seats} assentos" + "pt": "{seats} assentos", + "ca": "{seats} seients" }, "freeform": { "key": "seats", @@ -164,7 +169,8 @@ "pl": "Materiał: {material}", "pt_BR": "Material: {material}", "pt": "Material: {material}", - "eo": "Materialo: {material}" + "eo": "Materialo: {material}", + "ca": "Material: {material}" }, "freeform": { "key": "material", @@ -189,7 +195,8 @@ "fi": "Materiaali: puu", "pl": "Materiał: drewno", "pt": "Material: madeira", - "eo": "Materialo: ligna" + "eo": "Materialo: ligna", + "ca": "Material: fusta" } }, { @@ -209,7 +216,8 @@ "pl": "Materiał: metal", "pt_BR": "Material: metal", "pt": "Material: metal", - "eo": "Materialo: metala" + "eo": "Materialo: metala", + "ca": "Material: metall" } }, { @@ -230,7 +238,8 @@ "fi": "Materiaali: kivi", "pl": "Materiał: kamień", "pt": "Material: pedra", - "eo": "Materialo: ŝtona" + "eo": "Materialo: ŝtona", + "ca": "Material: pedra" } }, { @@ -251,7 +260,8 @@ "fi": "Materiaali: betoni", "pl": "Materiał: beton", "pt": "Material: concreto", - "eo": "Materialo: betona" + "eo": "Materialo: betona", + "ca": "Material: ciment" } }, { @@ -272,7 +282,8 @@ "fi": "Materiaali: muovi", "pl": "Materiał: plastik", "pt": "Material: plástico", - "eo": "Materialo: plasta" + "eo": "Materialo: plasta", + "ca": "Material: plàstic" } }, { @@ -293,7 +304,8 @@ "fi": "Materiaali: teräs", "pl": "Materiał: stal", "pt": "Material: aço", - "eo": "Materialo: ŝtala" + "eo": "Materialo: ŝtala", + "ca": "Material: acer" } } ], @@ -309,7 +321,8 @@ "zh_Hant": "這個長椅 (座位) 是什麼做的?", "pt_BR": "De que é feito o banco (assento)?", "pl": "Z czego wykonana jest ławka (siedzisko)?", - "pt": "De que é feito o banco (assento)?" + "pt": "De que é feito o banco (assento)?", + "es": "¿De que está hecho el banco (asiento)?" }, "id": "bench-material" }, @@ -341,7 +354,8 @@ "zh_Hant": "當坐在長椅時,那個人朝向 {direction}°。", "pl": "Siedząc na ławce, patrzy się w kierunku {direction}°.", "pt_BR": "Ao sentar-se no banco, olha-se para {direction} °.", - "pt": "Ao sentar-se no banco, olha-se para {direction} °." + "pt": "Ao sentar-se no banco, olha-se para {direction} °.", + "es": "¿Cuando está sentado en el banco, uno mira hacia {direction}º." }, "freeform": { "key": "direction", @@ -367,7 +381,8 @@ "pl": "Kolor: {colour}", "pt": "Cor: {colour}", "eo": "Koloro: {colour}", - "es": "Color: {colour}" + "es": "Color: {colour}", + "ca": "Color: {colour}" }, "question": { "en": "Which colour does this bench have?", @@ -406,7 +421,9 @@ "fi": "Väri: ruskea", "pl": "Kolor: brązowy", "pt": "Cor: castanho", - "eo": "Koloro: bruna" + "eo": "Koloro: bruna", + "ca": "Color: marró", + "es": "Color: marrón" } }, { @@ -427,7 +444,8 @@ "pl": "Kolor: zielony", "pt": "Cor: verde", "eo": "Koloro: verda", - "es": "Color: verde" + "es": "Color: verde", + "ca": "Color: verd" } }, { @@ -448,7 +466,8 @@ "pl": "Kolor: szary", "pt": "Cor: cinzento", "eo": "Koloro: griza", - "es": "Color: gris" + "es": "Color: gris", + "ca": "Color: gris" } }, { @@ -469,7 +488,8 @@ "pl": "Kolor: biały", "pt": "Cor: branco", "eo": "Koloro: blanka", - "es": "Color: blanco" + "es": "Color: blanco", + "ca": "Color: blanc" } }, { @@ -490,7 +510,8 @@ "pl": "Kolor: czerwony", "pt": "Cor: vermelho", "eo": "Koloro: ruĝa", - "es": "Color: rojo" + "es": "Color: rojo", + "ca": "Color: vermell" } }, { @@ -511,7 +532,8 @@ "pl": "Kolor: czarny", "pt": "Cor: preto", "eo": "Koloro: nigra", - "es": "Color: negro" + "es": "Color: negro", + "ca": "Color: negre" } }, { @@ -532,7 +554,8 @@ "pl": "Kolor: niebieski", "pt": "Cor: azul", "eo": "Koloro: blua", - "es": "Color: azul" + "es": "Color: azul", + "ca": "Color: blau" } }, { @@ -553,7 +576,8 @@ "pl": "Kolor: żółty", "pt": "Cor: amarelo", "eo": "Koloro: flava", - "es": "Color: amarillo" + "es": "Color: amarillo", + "ca": "Color: groc" } } ], @@ -571,7 +595,8 @@ "zh_Hant": "上一次探察長椅是什麼時候?", "pt_BR": "Quando esta bancada foi pesquisada pela última vez?", "pl": "Kiedy ostatnio badano tę ławkę?", - "pt": "Quando esta bancada foi pesquisada pela última vez?" + "pt": "Quando esta bancada foi pesquisada pela última vez?", + "es": "¿Cuándo fue la última vez que se inspeccionó este banco?" }, "render": { "en": "This bench was last surveyed on {survey:date}", @@ -584,7 +609,8 @@ "zh_Hant": "這個長椅最後是在 {survey:date} 探查的", "pt_BR": "Esta bancada foi pesquisada pela última vez em {survey:date}", "pl": "Ławka ta była ostatnio badana w dniu {survey:date}", - "pt": "Esta bancada foi pesquisada pela última vez em {survey:date}" + "pt": "Esta bancada foi pesquisada pela última vez em {survey:date}", + "es": "Este banco se inspeccionó por última vez el {survey:date}" }, "freeform": { "key": "survey:date", @@ -619,7 +645,8 @@ "pt_BR": "uma banco", "fi": "penkki", "pl": "Ławka", - "pt": "uma banco" + "pt": "uma banco", + "ca": "un banc" }, "presiceInput": { "preferredBackground": "photo" @@ -656,6 +683,8 @@ "description": { "nl": "Deze laag toont zitbanken en enkele vragen over deze zitbanken", "en": "A bench is a wooden, metal, stone, ... surface where a human can sit. This layers visualises them and asks a few questions about them.", - "fr": "Un banc est une surface en bois, métal, pierre... sur laquelle un humain peut s'asseoir. Cette couche permet de les visualiser et pose des questions à leur sujet." + "fr": "Un banc est une surface en bois, métal, pierre... sur laquelle un humain peut s'asseoir. Cette couche permet de les visualiser et pose des questions à leur sujet.", + "de": "Diese Karte stellt Sitzbänke aus Holz, Metall, Stein, ... dar und stellt ein paar Fragen, um weitere Informationen zu ergänzen.", + "es": "Un banco es una superficie de madera, metal, piedra, ... donde un humano se puede sentar. Estas capas los visualizan y preguntan algunas preguntas sobre ellos." } } \ No newline at end of file diff --git a/assets/layers/bench_at_pt/bench_at_pt.json b/assets/layers/bench_at_pt/bench_at_pt.json index cc0cedf11..b2cee12c6 100644 --- a/assets/layers/bench_at_pt/bench_at_pt.json +++ b/assets/layers/bench_at_pt/bench_at_pt.json @@ -42,7 +42,8 @@ "pt_BR": "Banco", "fi": "Penkki", "pl": "Ławka", - "pt": "Banco" + "pt": "Banco", + "ca": "Banc" }, "mappings": [ { @@ -65,7 +66,8 @@ "zh_Hant": "大眾運輸站點的長椅", "pt_BR": "Banco em ponto de transporte público", "pl": "Ławka na przystanku komunikacji miejskiej", - "pt": "Banco em ponto de transporte público" + "pt": "Banco em ponto de transporte público", + "es": "Banco en una parada de transporte público" } }, { @@ -109,7 +111,8 @@ "pl": "{name}", "pt": "{name}", "eo": "{name}", - "es": "{name}" + "es": "{name}", + "ca": "{name}" }, "freeform": { "key": "name" @@ -154,7 +157,8 @@ "en": "There is no bench here", "fr": "Il n'y a pas de banc ici", "de": "Hier gibt es keine Bank", - "nl": "Er is hier geen bank" + "nl": "Er is hier geen bank", + "es": "No hay ningún banco aquí" } } ] @@ -185,6 +189,7 @@ "en": "A layer showing all public-transport-stops which do have a bench", "es": "Una capa que muestra todas las paradas de transporte público que tienen bancos", "nl": "Een laag die stopplaatsen van openbaar vervoer toont waar er een zitbank is", - "fr": "Une couche montrant tous les arrêts de transports publics qui ont un banc" + "fr": "Une couche montrant tous les arrêts de transports publics qui ont un banc", + "de": "Eine Ebene mit allen Haltestellen des öffentlichen Nahverkehrs, die über eine Sitzbank verfügen" } } \ No newline at end of file diff --git a/assets/layers/bicycle_library/bicycle_library.json b/assets/layers/bicycle_library/bicycle_library.json index 090648c50..cd50c836b 100644 --- a/assets/layers/bicycle_library/bicycle_library.json +++ b/assets/layers/bicycle_library/bicycle_library.json @@ -9,7 +9,8 @@ "zh_Hant": "單車圖書館", "pt_BR": "Biblioteca de bicicleta", "de": "Fahrradbibliotheken", - "pt": "Biblioteca de bicicleta" + "pt": "Biblioteca de bicicleta", + "ca": "Biblioteca per a bicicletes" }, "minzoom": 8, "source": { @@ -25,7 +26,8 @@ "zh_Hant": "單車圖書館", "pt_BR": "Biblioteca de bicicleta", "de": "Fahrradbibliothek", - "pt": "Biblioteca de bicicleta" + "pt": "Biblioteca de bicicleta", + "ca": "Biblioteca per a bicicletes" }, "mappings": [ { @@ -120,7 +122,8 @@ "nb_NO": "Sykkelleie koster {charge}", "zh_Hant": "租借單車需要 {charge}", "pt_BR": "Custos de empréstimo de bicicleta {charge}", - "pt": "Custos de empréstimo de bicicleta {charge}" + "pt": "Custos de empréstimo de bicicleta {charge}", + "es": "Alquilar una bicicleta cuesta {charge}" }, "freeform": { "key": "charge", @@ -201,7 +204,8 @@ "ru": "Доступны детские велосипеды", "zh_Hant": "提供兒童單車", "pt_BR": "Bicicletas para crianças disponíveis", - "pt": "Bicicletas para crianças disponíveis" + "pt": "Bicicletas para crianças disponíveis", + "es": "Bicicletas para niños disponibles" } }, { @@ -215,7 +219,8 @@ "ru": "Доступны велосипеды для взрослых", "zh_Hant": "有提供成人單車", "pt_BR": "Bicicletas para adulto disponíveis", - "pt": "Bicicletas para adulto disponíveis" + "pt": "Bicicletas para adulto disponíveis", + "es": "Bicicletas para adultos disponibles" } }, { @@ -229,7 +234,8 @@ "ru": "Доступны велосипеды для людей с ограниченными возможностями", "zh_Hant": "有提供行動不便人士的單車", "pt_BR": "Bicicletas para deficientes físicos disponíveis", - "pt": "Bicicletas para deficientes físicos disponíveis" + "pt": "Bicicletas para deficientes físicos disponíveis", + "es": "Bicicletas para discapacitados disponibles" } } ] diff --git a/assets/layers/bicycle_rental/bicycle_rental.json b/assets/layers/bicycle_rental/bicycle_rental.json index 1dfb14d4a..71443941e 100644 --- a/assets/layers/bicycle_rental/bicycle_rental.json +++ b/assets/layers/bicycle_rental/bicycle_rental.json @@ -25,7 +25,8 @@ "render": { "en": "Bicycle rental", "nl": "Fietsverhuur", - "es": "Alquiler de bicicletas" + "es": "Alquiler de bicicletas", + "de": "Fahrradverleih" }, "mappings": [ { @@ -36,7 +37,10 @@ }, "then": { "en": "{name}", - "nl": "{name}" + "nl": "{name}", + "ca": "{name}", + "de": "{name}", + "es": "{name}" } } ] @@ -44,7 +48,9 @@ "description": { "en": "Bicycle rental stations", "nl": "Fietsverhuustations", - "fr": "Station de location de vélo" + "fr": "Station de location de vélo", + "de": "Fahrradverleihstationen", + "es": "Estaciones de alquiler de bicicletas" }, "tagRenderings": [ "images", @@ -52,7 +58,9 @@ "id": "bicycle_rental_type", "question": { "en": "What kind of bicycle rental is this?", - "nl": "Wat voor fietsverhuur is dit?" + "nl": "Wat voor fietsverhuur is dit?", + "de": "Was ist das für ein Fahrradverleih?", + "es": "¿Qué tipo de alquiler de bicicletas es este?" }, "mappings": [ { @@ -64,7 +72,9 @@ }, "then": { "en": "This is a shop whose main focus is bicycle rental", - "nl": "Dit is een zaak die focust op fietsverhuur" + "nl": "Dit is een zaak die focust op fietsverhuur", + "de": "Dies ist ein Geschäft, dessen Schwerpunkt auf dem Fahrradverleih liegt", + "es": "Esta es una tienda que se centra en el alquiler de bicicletas" } }, { @@ -76,21 +86,27 @@ }, "then": { "en": "This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is not the main focus", - "nl": "Dit is een zaak die verschillende voorwerpen en/of voertuigen verhuurt, waaronder ook fietsen; al zijn fietsen niet de hoofdfocus" + "nl": "Dit is een zaak die verschillende voorwerpen en/of voertuigen verhuurt, waaronder ook fietsen; al zijn fietsen niet de hoofdfocus", + "de": "Dies ist ein Vermietungsunternehmen, das verschiedene Gegenstände und/oder Fahrzeuge vermietet. Es vermietet auch Fahrräder, aber das ist nicht der Hauptschwerpunkt", + "es": "Este es un negocio de alquileres que alquila varios objetos y/o vehículos. También alquila bicicletas, pero este no es el enfoque principal" } }, { "if": "bicycle_rental=docking_station", "then": { "en": "This is a shop which sells or repairs bicycles, but also rents out bicycles", - "nl": "Dit is een fietsenmaker of fietswinkel die ook fietsen verhuurt" + "nl": "Dit is een fietsenmaker of fietswinkel die ook fietsen verhuurt", + "de": "Dies ist ein Geschäft, das Fahrräder verkauft oder repariert, aber auch Fahrräder vermietet", + "es": "Esta es una tienda que vende o alquila bicicletas, pero también las alquila" } }, { "if": "bicycle_rental=key_dispensing_machine", "then": { "en": "This is an automated docking station, where a bicycle is mechanically locked into a structure", - "nl": "Dit is een docking station waar de fietsen mechanisch in een grotere structuur worden vastgemaakt" + "nl": "Dit is een docking station waar de fietsen mechanisch in een grotere structuur worden vastgemaakt", + "de": "Dies ist eine automatisierte Dockingstation, bei der ein Fahrrad mechanisch in einer Struktur verriegelt wird", + "es": "Esta es una estación automática, en la que una bici se asegura mecánicamente en una estructura" } }, { @@ -98,7 +114,8 @@ "then": { "en": "A machine is present which dispenses and accepts keys, eventually after authentication and/or payment. The bicycles are parked nearby", "nl": "Hier is een machine die fietssleutels verdeelt en terugneemt, eventueel na aanmelden of betaling. De fietsen staan in de buurt geparkeerd", - "hu": "Ez egy leadási pont: ennek a kerékpárkölcsönzőnek a kijelölt kerékpártárolója" + "hu": "Ez egy leadási pont: ennek a kerékpárkölcsönzőnek a kijelölt kerékpártárolója", + "de": "Es gibt einen Automaten, der Schlüssel ausgibt und annimmt, eventuell nach Authentifizierung und/oder Bezahlung. Die Fahrräder sind in der Nähe geparkt" } } ], @@ -137,11 +154,15 @@ ], "question": { "en": "What kind of bicycles and accessories are rented here?", - "nl": "Wat voor soort fietsen en fietstoebehoren worden hier verhuurd?" + "nl": "Wat voor soort fietsen en fietstoebehoren worden hier verhuurd?", + "de": "Welche Art von Fahrrädern und Zubehör wird hier vermietet?", + "es": "¿Qué tipo de bicicletas y accesorios se alquilan aquí?" }, "render": { "en": "{rental} is rented here", - "nl": "{rental} kunnen hier uitgeleend worden" + "nl": "{rental} kunnen hier uitgeleend worden", + "de": "{rental} wird hier vermietet", + "es": "{rental} se alquilan aquí" }, "freeform": { "key": "rental", @@ -153,49 +174,62 @@ "if": "rental=city_bike", "then": { "en": "Normal city bikes can be rented here", - "nl": "Gewone stadsfietsen kunnen hier gehuurd worden" + "nl": "Gewone stadsfietsen kunnen hier gehuurd worden", + "de": "Normale Stadtfahrräder können hier gemietet werden", + "es": "Aquí se pueden alquilar bicis normales" } }, { "if": "rental=ebike", "then": { "en": "Electrical bikes can be rented here", - "nl": "Elektrische fietsen kunnen hier gehuurd worden" + "nl": "Elektrische fietsen kunnen hier gehuurd worden", + "de": "Elektrofahrräder können hier gemietet werden", + "es": "Aquí se pueden alquilar bicis eléctricas" } }, { "if": "rental=bmx", "then": { "en": "BMX bikes can be rented here", - "nl": "BMX-fietsen kunnen hier gehuurd worden" + "nl": "BMX-fietsen kunnen hier gehuurd worden", + "de": "BMX-Räder können hier gemietet werden", + "es": "Aquí se pueden alquilar bicis BMX" } }, { "if": "rental=mtb", "then": { "en": "Mountainbikes can be rented here", - "nl": "Mountainbikes kunnen hier gehuurd worden" + "nl": "Mountainbikes kunnen hier gehuurd worden", + "de": "Mountainbikes können hier gemietet werden", + "es": "Aquí se pueden alquilar bicis de montaña" } }, { "if": "rental=kid_bike", "then": { "en": "Bikes for childs can be rented here", - "nl": "Kinderfietsen kunnen hier gehuurd worden" + "nl": "Kinderfietsen kunnen hier gehuurd worden", + "de": "Kinderfahrräder können hier gemietet werden", + "es": "Aquí se pueden alquilar bicis infantiles" } }, { "if": "rental=tandem", "then": { "en": "Tandem bicycles can be rented here", - "nl": "Tandems kunnen hier gehuurd worden" + "nl": "Tandems kunnen hier gehuurd worden", + "de": "Tandems können hier gemietet werden" } }, { "if": "rental=racebike", "then": { "en": "Race bicycles can be rented here", - "nl": "Wielerfietsen (sportfietsen) kunnen hier gehuurd worden" + "nl": "Wielerfietsen (sportfietsen) kunnen hier gehuurd worden", + "de": "Rennräder können hier gemietet werden", + "es": "Aquí se pueden alquilar bicicletas de carreras" } } ] @@ -211,49 +245,63 @@ "city_bike", { "en": "city bikes", - "nl": "stadsfietsen" + "nl": "stadsfietsen", + "de": "Stadträder", + "es": "bicis de ciudad" } ], [ "ebike", { "en": "electrical bikes", - "nl": "elektrische fietsen" + "nl": "elektrische fietsen", + "de": "Elektrofahrräder", + "es": "bicis eléctricas" } ], [ "kid_bike", { "en": "bikes for children", - "nl": "kinderfietsen" + "nl": "kinderfietsen", + "de": "Kinderfahrräder", + "es": "bicis infantiles" } ], [ "bmx", { "en": "BMX bikes", - "nl": "BMX-fietsen" + "nl": "BMX-fietsen", + "de": "BMX-Räder", + "es": "bicis BMX" } ], [ "mtb", { "en": "mountainbike", - "nl": "mountainbike" + "nl": "mountainbike", + "ca": "bicicleta de muntanya", + "de": "Mountainbikes", + "es": "bicis de montaña" } ], [ "bicycle_pannier", { "en": "bicycle panniers", - "nl": "fietstassen" + "nl": "fietstassen", + "de": "Fahrradtaschen" } ], [ "tandem_bicycle", { "en": "tandem", - "nl": "tandem" + "nl": "tandem", + "ca": "tàndem", + "de": "Tandems" } ] ] @@ -286,7 +334,9 @@ "title": { "en": "a bicycle rental shop", "nl": "een fietsverhuurzaak", - "fr": "une magasin de location de vélos" + "fr": "une magasin de location de vélos", + "de": "Ein Fahrradverleih", + "es": "una tienda de alquiler de bicicletas" }, "tags": [ "amenity=bicycle_rental", @@ -295,13 +345,15 @@ "description": { "en": "A manned shop which focuses on bicycle rental", "nl": "Een bemande winkel die focust op fietsverhuur", - "fr": "Un magasin qui priorise la location de vélos" + "fr": "Un magasin qui priorise la location de vélos", + "de": "Ein Geschäft, das sich auf den Fahrradverleih konzentriert" } }, { "title": { "en": "a bicycle rental", - "nl": "een fietsverhuur" + "nl": "een fietsverhuur", + "de": "Ein Fahrradverleih" }, "tags": [ "amenity=bicycle_rental" @@ -346,7 +398,9 @@ "explanation": { "nl": "{title()} is permanent gestopt", "en": "{title()} has closed down permanently", - "fr": "{title()} a était fermé de façon permanente" + "fr": "{title()} a était fermé de façon permanente", + "de": "{title()} ist dauerhaft geschlossen", + "es": "{title()} ha cerrado permanentemente" }, "changesetMessage": "shop_closed" } @@ -361,7 +415,9 @@ "then": { "en": "This bicycle shop used to rent out bikes but doesn't rent out bikes anymore", "nl": "Deze fietszaak verhuurde vroeger fietsen, maar nu niet meer", - "fr": "Ce magasin de vélo louait des vélos, mais n'en loue plus maintenant" + "fr": "Ce magasin de vélo louait des vélos, mais n'en loue plus maintenant", + "de": "Dieser Fahrradladen vermietete früher Fahrräder, aber jetzt nicht mehr", + "es": "Esta tienda de bicicletas alquilaba bicis, pero ya no lo hace" } } ] diff --git a/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json b/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json index 11454cadc..b492111aa 100644 --- a/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json +++ b/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json @@ -78,7 +78,8 @@ "de": "Ist dieser Automat noch in Betrieb?", "zh_Hant": "這個自動販賣機仍有運作嗎?", "pt_BR": "Esta máquina de venda automática ainda está operacional?", - "pt": "Esta máquina de venda automática ainda está operacional?" + "pt": "Esta máquina de venda automática ainda está operacional?", + "es": "¿Todavía es operacional esta máquina exprendedora?" }, "render": { "en": "The operational status is {operational_status}", @@ -89,7 +90,8 @@ "ru": "Рабочий статус: {operational_status}", "zh_Hant": "運作狀態是 {operational_status}", "pt_BR": "O estado operacional é: {operational_status}", - "pt": "O estado operacional é: {operational_status}" + "pt": "O estado operacional é: {operational_status}", + "es": "El estado operacional es {operational_status}" }, "freeform": { "key": "operational_status" @@ -124,7 +126,8 @@ "de": "Dieser Automat ist kaputt", "zh_Hant": "這個自動販賣機沒有運作了", "pt_BR": "Esta máquina de venda automática está quebrada", - "pt": "Esta máquina de venda automática está quebrada" + "pt": "Esta máquina de venda automática está quebrada", + "es": "Esta máquina exprendedora está rota" } }, { @@ -140,7 +143,8 @@ "de": "Dieser Automat ist geschlossen", "zh_Hant": "這個自動販賣機已經關閉了", "pt_BR": "Esta máquina de venda automática está fechada", - "pt": "Esta máquina de venda automática está fechada" + "pt": "Esta máquina de venda automática está fechada", + "es": "Esta máquina exprendedora está cerrada" } } ], @@ -287,6 +291,7 @@ ], "description": { "en": "A layer showing vending machines for bicycle tubes (either purpose-built bicycle tube vending machines or classical vending machines with bicycle tubes and optionally additional bicycle related objects such as lights, gloves, locks, ...)", - "nl": "Een laag met verkoopsautomaten met binnenbanden voor fietsen (dit kan een automaat zijn met énkel fietsbanden, of een gewone automaat met fietsbanden en andere fietsaccessoires zoals lichten, handschoenen, sloten,...)" + "nl": "Een laag met verkoopsautomaten met binnenbanden voor fietsen (dit kan een automaat zijn met énkel fietsbanden, of een gewone automaat met fietsbanden en andere fietsaccessoires zoals lichten, handschoenen, sloten,...)", + "de": "Eine Ebene mit Automaten für Fahrradschläuche (entweder spezielle Fahrradschlauch-Automaten oder klassische Automaten mit Fahrradschläuchen und optional zusätzlichen fahrradbezogenen Gegenständen wie Lampen, Handschuhe, Schlösser, ...)" } } \ No newline at end of file diff --git a/assets/layers/bike_cafe/bike_cafe.json b/assets/layers/bike_cafe/bike_cafe.json index ba794e6d3..4e59b2660 100644 --- a/assets/layers/bike_cafe/bike_cafe.json +++ b/assets/layers/bike_cafe/bike_cafe.json @@ -11,7 +11,8 @@ "ru": "Велосипедное кафе", "zh_Hant": "單車咖啡廳", "pt_BR": "Café de bicicletas", - "pt": "Café de bicicletas" + "pt": "Café de bicicletas", + "ca": "Cafeteria per a bicicletes" }, "minzoom": 13, "source": { @@ -50,7 +51,8 @@ "ru": "Велосипедное кафе", "zh_Hant": "單車咖啡廳", "pt_BR": "Café de bicicleta", - "pt": "Café de bicicleta" + "pt": "Café de bicicleta", + "ca": "Cafeteria per a bicicletes" }, "mappings": [ { @@ -282,7 +284,8 @@ "zh_Hans": "{name}的电话号码是什么?", "zh_Hant": "{name} 的電話號碼是?", "pt_BR": "Qual o número de telefone de {name}?", - "pt": "Qual é o número de telefone de {name}?" + "pt": "Qual é o número de telefone de {name}?", + "es": "¿Cual es el número de teléfono de {name}?" }, "render": "{phone}", "freeform": { @@ -303,7 +306,8 @@ "zh_Hans": "{name}的电子邮箱是什么?", "zh_Hant": "{name} 的電子郵件地址是?", "pt_BR": "Qual o endereço de email de {name}?", - "pt": "Qual o endereço de email de {name}?" + "pt": "Qual o endereço de email de {name}?", + "es": "¿Cual es la dirección de correo electrónico de {name}?" }, "render": "{email}", "freeform": { @@ -378,6 +382,7 @@ ], "description": { "en": "A bike café is a café geared towards cyclists, for example with services such as a pump, with lots of bicycle-related decoration, ...", - "nl": "Een fietscafé is een café dat gericht is op fietsers, bijvoorbeeld omdat het een fietspomp heeft, fietsgerelateerde decoratie heeft enzovoorts." + "nl": "Een fietscafé is een café dat gericht is op fietsers, bijvoorbeeld omdat het een fietspomp heeft, fietsgerelateerde decoratie heeft enzovoorts.", + "de": "Ein Fahrradcafé ist ein Café, das auf Radfahrer ausgerichtet ist, zum Beispiel mit Dienstleistungen wie einer Pumpe, mit viel fahrradbezogener Dekoration, ..." } } \ No newline at end of file diff --git a/assets/layers/bike_cleaning/bike_cleaning.json b/assets/layers/bike_cleaning/bike_cleaning.json index ceaf9c90c..18f5c389a 100644 --- a/assets/layers/bike_cleaning/bike_cleaning.json +++ b/assets/layers/bike_cleaning/bike_cleaning.json @@ -9,7 +9,8 @@ "zh_Hant": "單車清理服務", "pt_BR": "Serviço de limpeza de bicicletas", "pt": "Serviço de limpeza de bicicletas", - "ru": "Услуги по чистке велосипедов" + "ru": "Услуги по чистке велосипедов", + "es": "Servicio de limpieza de bicis" }, "title": { "render": { @@ -21,7 +22,8 @@ "zh_Hant": "單車清理服務", "pt_BR": "Serviço de limpeza de bicicletas", "pt": "Serviço de limpeza de bicicletas", - "ru": "Услуги по чистке велосипедов" + "ru": "Услуги по чистке велосипедов", + "es": "Servicio de limpieza de bicis" }, "mappings": [ { @@ -34,7 +36,8 @@ "de": "Fahrrad-Reinigungsdienst{name}", "zh_Hant": "單車清理服務 {name}", "pt_BR": "Serviço de limpeza de bicicletas {name}", - "pt": "Serviço de limpeza de bicicletas {name}" + "pt": "Serviço de limpeza de bicicletas {name}", + "es": "Servicio de limpieza de bicis {name}" } } ] @@ -61,7 +64,8 @@ "zh_Hant": "單車清理服務", "pt_BR": "uma serviço de limpeza de bicicletas", "pt": "uma serviço de limpeza de bicicletas", - "ru": "Услуги по чистке велосипедов" + "ru": "Услуги по чистке велосипедов", + "es": "un servicio de limpieza de bicis" }, "tags": [ "amenity=bicycle_wash" @@ -74,12 +78,14 @@ "question": { "en": "How much does it cost to use the cleaning service?", "de": "Wie viel kostet die Nutzung des Reinigungsdienstes?", - "nl": "Hoeveel kost het gebruik van het fietsschoonmaakpunt?" + "nl": "Hoeveel kost het gebruik van het fietsschoonmaakpunt?", + "es": "¿Cuánto cuesta utilizar el servicio de limpieza?" }, "render": { "en": "Using the cleaning service costs {service:bicycle:cleaning:charge}", "de": "Nutzung des Reinigungsservice kostet {service:bicycle:cleaning:charge}", - "nl": "Het gebruik van het fietsschoonmaakpunt kost {service:bicycle:cleaning:charge}" + "nl": "Het gebruik van het fietsschoonmaakpunt kost {service:bicycle:cleaning:charge}", + "es": "Utilizar el servicio de limpieza cuesta {service:bicycle:cleaning:charge}" }, "condition": { "and": [ @@ -100,7 +106,8 @@ "then": { "en": "The cleaning service is free to use", "de": "Der Reinigungsservice ist kostenlos", - "nl": "Het fietsschoonmaakpunt is gratis" + "nl": "Het fietsschoonmaakpunt is gratis", + "es": "El servicio de limpieza es gratis" } }, { @@ -108,7 +115,8 @@ "then": { "en": "Free to use", "de": "Kostenlose Nutzung", - "nl": "Gratis te gebruiken" + "nl": "Gratis te gebruiken", + "es": "Gratis" }, "hideInAnswer": true }, @@ -117,7 +125,8 @@ "then": { "en": "The cleaning service has a fee, but the amount is not known", "de": "Der Reinigungsdienst ist kostenpflichtig, aber der Betrag ist nicht bekannt", - "nl": "Het fietsschoonmaakpunt is betalend, maar de prijs is onbekend" + "nl": "Het fietsschoonmaakpunt is betalend, maar de prijs is onbekend", + "es": "El servicio de limpieza tiene una tasa, pero la cantidad se desconoce" }, "hideInAnswer": true } @@ -128,12 +137,14 @@ "question": { "en": "How much does it cost to use the cleaning service?", "de": "Wie viel kostet die Nutzung des Reinigungsdienstes?", - "nl": "Hoeveel kost het gebruik van het fietsschoonmaakpunt?" + "nl": "Hoeveel kost het gebruik van het fietsschoonmaakpunt?", + "es": "¿Cuánto cuesta utilizar el servicio de limpieza?" }, "render": { "en": "Using the cleaning service costs {charge}", "de": "Die Nutzung des Reinigungsdienstes kostet {charge}", - "nl": "Het gebruik van het fietsschoonmaakpunt kost {charge}" + "nl": "Het gebruik van het fietsschoonmaakpunt kost {charge}", + "es": "Utilizar el servicio de limpieza cuesta {charge}" }, "condition": { "or": [ @@ -153,7 +164,8 @@ "then": { "en": "Free to use cleaning service", "de": "Kostenloser Reinigungsservice", - "nl": "Gratis fietsschoonmaakpunt" + "nl": "Gratis fietsschoonmaakpunt", + "es": "Un servicio de limpieza gratis" } }, { @@ -161,7 +173,8 @@ "then": { "en": "Free to use", "de": "Kostenlose Nutzung", - "nl": "Gratis te gebruiken" + "nl": "Gratis te gebruiken", + "es": "Gratis" }, "hideInAnswer": true }, @@ -170,7 +183,8 @@ "then": { "en": "The cleaning service has a fee", "de": "Der Reinigungsservice ist kostenpflichtig", - "nl": "Je moet betalen voor het fietsschoonmaakpunt" + "nl": "Je moet betalen voor het fietsschoonmaakpunt", + "es": "El servicio de limpieza tiene una tarifa" } } ], @@ -219,6 +233,8 @@ ], "description": { "en": "A layer showing facilities where one can clean their bike", - "nl": "Een laag die plaatsen toont waar je je fiets kunt wassen" + "nl": "Een laag die plaatsen toont waar je je fiets kunt wassen", + "de": "Eine Ebene mit Einrichtungen, in denen man sein Fahrrad reinigen kann", + "es": "Una capa que muestra facilidades en las que uno puede limpiar su bici" } } \ No newline at end of file diff --git a/assets/layers/bike_parking/bike_parking.json b/assets/layers/bike_parking/bike_parking.json index b97f46141..b4fae0a94 100644 --- a/assets/layers/bike_parking/bike_parking.json +++ b/assets/layers/bike_parking/bike_parking.json @@ -12,7 +12,9 @@ "ru": "Велосипедная парковка", "pl": "Parking dla rowerów", "pt_BR": "Estacionamento de bicicletas", - "pt": "Estacionamento de bicicletas" + "pt": "Estacionamento de bicicletas", + "ca": "Aparcament per a bicicletes", + "es": "Aparcamiento de bicis" }, "minzoom": 17, "source": { @@ -36,7 +38,8 @@ "ru": "Велосипедная парковка", "pl": "Parking dla rowerów", "pt_BR": "uma estacionamento de bicicletas", - "pt": "uma estacionamento de bicicletas" + "pt": "uma estacionamento de bicicletas", + "es": "un aparcamiento de bicis" }, "tags": [ "amenity=bicycle_parking" @@ -56,7 +59,9 @@ "ru": "Велосипедная парковка", "pl": "Parking dla rowerów", "pt_BR": "Estacionamento de bicicletas", - "pt": "Estacionamento de bicicletas" + "pt": "Estacionamento de bicicletas", + "ca": "Aparcament per a bicicletes", + "es": "Aparcamiento de bicis" } }, "tagRenderings": [ @@ -74,7 +79,8 @@ "zh_Hant": "這是那種類型的單車停車場?", "pl": "Jaki jest typ tego parkingu dla rowerów?", "pt_BR": "Qual o tipo deste estacionamento de bicicletas?", - "pt": "Qual o tipo deste estacionamento de bicicletas?" + "pt": "Qual o tipo deste estacionamento de bicicletas?", + "es": "¿Cual es el tipo de este aparcamiento de bicicletas?" }, "render": { "en": "This is a bicycle parking of the type: {bicycle_parking}", @@ -88,7 +94,8 @@ "ru": "Это велопарковка типа {bicycle_parking}", "pl": "Jest to parking rowerowy typu: {bicycle_parking}", "pt_BR": "Este é um estacionamento de bicicletas do tipo: {bicycle_parking}", - "pt": "Este é um estacionamento de bicicletas do tipo: {bicycle_parking}" + "pt": "Este é um estacionamento de bicicletas do tipo: {bicycle_parking}", + "es": "Este es un aparcamiento de bicicletas del tipo: {bicycle_parking}" }, "freeform": { "key": "bicycle_parking", @@ -107,7 +114,8 @@ "de": "Fahrradbügel", "hu": "Korlát", "it": "Archetti", - "zh_Hant": "單車架" + "zh_Hant": "單車架", + "ca": "Bastidors de grapes" }, "icon": { "path": "./assets/layers/bike_parking/staple.svg", @@ -124,7 +132,8 @@ "de": "Metallgestänge", "hu": "Kerékbefogó hurok", "it": "Scolapiatti", - "zh_Hant": "車輪架/圓圈" + "zh_Hant": "車輪架/圓圈", + "ca": "Portarodes/bucles" }, "icon": { "path": "./assets/layers/bike_parking/wall_loops.svg", @@ -140,7 +149,8 @@ "gl": "Cadeado para guiador", "de": "Halter für Fahrradlenker", "it": "Blocca manubrio", - "zh_Hant": "車把架" + "zh_Hant": "車把架", + "ca": "Suport de manillar" }, "icon": { "path": "./assets/layers/bike_parking/handlebar_holder.svg", @@ -157,7 +167,8 @@ "de": "Gestell", "zh_Hant": "車架", "it": "Rastrelliera", - "ru": "Стойка" + "ru": "Стойка", + "ca": "Enganxament" }, "icon": { "path": "./assets/layers/bike_parking/rack.svg", @@ -175,7 +186,8 @@ "hu": "Kétszintű", "zh_Hant": "兩層", "it": "A due piani", - "ru": "Двухуровневая" + "ru": "Двухуровневая", + "ca": "De dos nivells" }, "icon": { "path": "./assets/layers/bike_parking/two_tier.svg", @@ -193,7 +205,8 @@ "hu": "Fészer", "zh_Hant": "車棚", "it": "Rimessa", - "ru": "Навес" + "ru": "Навес", + "es": "Caseta" }, "icon": { "path": "./assets/layers/bike_parking/shed.svg", @@ -208,7 +221,9 @@ "fr": "Potelet", "it": "Colonnina", "de": "Poller", - "zh_Hant": "柱子" + "zh_Hant": "柱子", + "ca": "Pilona", + "es": "Bolardo" }, "icon": { "path": "./assets/layers/bike_parking/bollard.svg", @@ -223,7 +238,8 @@ "fr": "Zone au sol qui est marquée pour le stationnement des vélos", "it": "Una zona del pavimento che è marcata per il parcheggio delle bici", "de": "Ein Bereich auf dem Boden, der für das Abstellen von Fahrrädern gekennzeichnet ist", - "zh_Hant": "樓層當中標示為單車停車場的區域" + "zh_Hant": "樓層當中標示為單車停車場的區域", + "es": "Una área en el suelo que está marcada para el aparcamiento de bicicletas" } } ], @@ -239,7 +255,8 @@ "pl": "Jaka jest względna lokalizacja tego parkingu rowerowego?", "pt_BR": "Qual a localização relativa deste estacionamento de bicicletas?", "de": "Wo befinden sich diese Fahrradabstellplätze?", - "pt": "Qual a localização relativa deste estacionamento de bicicletas?" + "pt": "Qual a localização relativa deste estacionamento de bicicletas?", + "es": "¿Cual es la localización relativa de este aparcamiento de bicicletas?" }, "mappings": [ { @@ -253,7 +270,9 @@ "de": "Tiefgarage", "zh_Hant": "地下停車場", "pt_BR": "Estacionamento subterrâneo", - "pt": "Estacionamento subterrâneo" + "pt": "Estacionamento subterrâneo", + "ca": "Aparcament subterrani", + "es": "Aparcamiento subterráneo" } }, { @@ -268,7 +287,8 @@ "zh_Hant": "地面停車場", "pt_BR": "Estacionamento de superfície", "pt": "Estacionamento de superfície", - "hu": "Felszíni parkoló" + "hu": "Felszíni parkoló", + "es": "Aparcamiento a nivel de calle" } }, { @@ -283,7 +303,9 @@ "zh_Hant": "屋頂停車場", "pt_BR": "Estacionamento no telhado", "pt": "Estacionamento no telhado", - "ru": "Парковка на крыше" + "ru": "Парковка на крыше", + "ca": "Aparcament al terrat", + "es": "Aparcamiento de azotea" } }, { @@ -315,7 +337,8 @@ "it": "È un parcheggio coperto? Indicare “coperto” per parcheggi all’interno.", "zh_Hant": "這個停車場是否有車棚?如果是室內停車場也請選擇\"遮蔽\"。", "pt_BR": "Este estacionamento é coberto? Também selecione \"coberto\" para estacionamentos internos.", - "pt": "Este estacionamento é coberto? Também selecione \"coberto\" para estacionamentos internos." + "pt": "Este estacionamento é coberto? Também selecione \"coberto\" para estacionamentos internos.", + "es": "¿Está cubierto este aparcamiento? Selecciona \"cubierto\" también para aparcamientos interiores." }, "condition": { "and": [ @@ -337,7 +360,8 @@ "zh_Hant": "這個停車場有遮蔽 (有屋頂)", "ru": "Это крытая парковка (есть крыша/навес)", "pt_BR": "Este estacionamento é coberto (tem um telhado)", - "pt": "Este estacionamento é coberto (tem um telhado)" + "pt": "Este estacionamento é coberto (tem um telhado)", + "es": "Este aparcamiento está cubierto (tiene un tejado)" } }, { @@ -353,7 +377,8 @@ "zh_Hant": "這個停車場沒有遮蔽", "ru": "Это открытая парковка", "pt_BR": "Este estacionamento não é coberto", - "pt": "Este estacionamento não é coberto" + "pt": "Este estacionamento não é coberto", + "es": "Este aparcamiento no está cubierto" } } ], @@ -367,7 +392,8 @@ "gl": "Cantas bicicletas caben neste aparcadoiro de bicicletas (incluídas as posíbeis bicicletas de carga)?", "de": "Wie viele Fahrräder passen auf diesen Fahrrad-Parkplatz (einschließlich möglicher Lastenfahrräder)?", "it": "Quante biciclette entrano in questo parcheggio per bici (incluse le eventuali bici da trasporto)?", - "zh_Hant": "這個單車停車場能放幾台單車 (包括裝箱單車)?" + "zh_Hant": "這個單車停車場能放幾台單車 (包括裝箱單車)?", + "es": "¿Cuántas bicicletas caben en este aparcamiento de bicicletas (incluyendo posibles bicicletas de carga)?" }, "render": { "en": "Place for {capacity} bikes", @@ -379,7 +405,8 @@ "zh_Hant": "{capacity} 單車的地方", "ru": "Место для {capacity} велосипеда(ов)", "pt_BR": "Lugar para {capacity} bicicletas", - "pt": "Lugar para {capacity} bicicletas" + "pt": "Lugar para {capacity} bicicletas", + "es": "Espacio para {capacity} bicis" }, "freeform": { "key": "capacity", @@ -397,7 +424,8 @@ "zh_Hant": "誰可以使用這個單車停車場?", "ru": "Кто может пользоваться этой велопарковкой?", "pt_BR": "Quem pode usar este estacionamento de bicicletas?", - "pt": "Quem pode usar este estacionamento de bicicletas?" + "pt": "Quem pode usar este estacionamento de bicicletas?", + "es": "¿Quién puede utilizar este aparcamiento de bicicletas?" }, "render": { "en": "{access}", @@ -411,7 +439,9 @@ "fi": "{access}", "pt_BR": "{access}", "pt": "{access}", - "eo": "{access}" + "eo": "{access}", + "ca": "{access}", + "es": "{access}" }, "freeform": { "key": "access", @@ -430,7 +460,9 @@ "de": "Öffentlich zugänglich", "zh_Hant": "公開可用", "pt_BR": "Acessível ao público", - "pt": "Acessível ao público" + "pt": "Acessível ao público", + "ca": "Accessible al públic", + "es": "Accesible públicamente" } }, { @@ -443,7 +475,8 @@ "zh_Hant": "通行性主要是為了企業的顧客", "pt_BR": "Acesso é principalmente para visitantes de uma empresa", "de": "Der Zugang ist in erster Linie für Besucher eines Unternehmens bestimmt", - "pt": "Acesso é principalmente para visitantes de uma empresa" + "pt": "Acesso é principalmente para visitantes de uma empresa", + "es": "El acceso es primariamente para visitantes a un negocio" } }, { @@ -456,7 +489,8 @@ "zh_Hant": "通行性僅限學校、公司或組織的成員", "pt_BR": "Acesso é limitado aos membros de uma escola, companhia ou organização", "de": "Der Zugang ist beschränkt auf Mitglieder einer Schule, eines Unternehmens oder einer Organisation", - "pt": "Acesso é limitado aos membros de uma escola, companhia ou organização" + "pt": "Acesso é limitado aos membros de uma escola, companhia ou organização", + "es": "El acceso se limita a miembros de una escuela, compañía u organización" } } ], @@ -472,7 +506,8 @@ "it": "Questo parcheggio dispone di posti specifici per le bici da trasporto?", "zh_Hant": "這個單車停車場有地方放裝箱的單車嗎?", "pt_BR": "O estacionamento de bicicletas tem vagas para bicicletas de carga?", - "pt": "O estacionamento de bicicletas tem vagas para bicicletas de carga?" + "pt": "O estacionamento de bicicletas tem vagas para bicicletas de carga?", + "es": "¿Este aparcamiento de bicicletas tiene huevos para bicicletas de carga?" }, "mappings": [ { @@ -480,13 +515,14 @@ "then": { "en": "This parking has room for cargo bikes", "nl": "Deze parking heeft plaats voor bakfietsen", - "gl": "Este aparcadoiro ten espazo para bicicletas de carga.", + "gl": "Este aparcadoiro ten espazo para bicicletas de carga", "de": "Dieser Parkplatz bietet Platz für Lastenfahrräder", "fr": "Ce parking a de la place pour les vélos cargo", "it": "Questo parcheggio ha posto per bici da trasporto", "zh_Hant": "這個停車場有地方可以放裝箱單車", "pt_BR": "Este estacionamento tem vagas para bicicletas de carga", - "pt": "Este estacionamento tem vagas para bicicletas de carga" + "pt": "Este estacionamento tem vagas para bicicletas de carga", + "es": "Este aparcamiento tiene espacio para bicicletas de carga" } }, { @@ -500,7 +536,8 @@ "it": "Questo parcheggio ha posti destinati (ufficialmente) alle bici da trasporto.", "zh_Hant": "這停車場有設計 (官方) 空間給裝箱的單車。", "pt_BR": "Este estacionamento tem vagas (oficiais) projetadas para bicicletas de carga.", - "pt": "Este estacionamento tem vagas (oficiais) projetadas para bicicletas de carga." + "pt": "Este estacionamento tem vagas (oficiais) projetadas para bicicletas de carga.", + "es": "Este aparcamiento tiene huecos (oficialmente) designados para bicicletas de carga." } }, { @@ -513,7 +550,8 @@ "fr": "Il est interdit de garer des vélos cargo", "it": "Il parcheggio delle bici da trasporto è proibito", "pt_BR": "Você não tem permissão para estacionar bicicletas de carga", - "pt": "Não tem permissão para estacionar bicicletas de carga" + "pt": "Não tem permissão para estacionar bicicletas de carga", + "es": "No se permite aparcar bicicletas de carga" } } ], @@ -528,7 +566,8 @@ "de": "Wie viele Lastenfahrräder passen auf diesen Fahrrad-Parkplatz?", "it": "Quante bici da trasporto entrano in questo parcheggio per bici?", "pt_BR": "Quantas bicicletas de carga cabem neste estacionamento de bicicletas?", - "pt": "Quantas bicicletas de carga cabem neste estacionamento de bicicletas?" + "pt": "Quantas bicicletas de carga cabem neste estacionamento de bicicletas?", + "es": "¿Cuántas bicicletas de carga caben en este aparcamiento de bicicletas?" }, "render": { "en": "This parking fits {capacity:cargo_bike} cargo bikes", @@ -538,7 +577,8 @@ "de": "Auf diesen Parkplatz passen {capacity:cargo_bike} Lastenfahrräder", "it": "Questo parcheggio può contenere {capacity:cargo_bike} bici da trasporto", "pt_BR": "Neste estacionamento cabem {capacity:cargo_bike} bicicletas de carga", - "pt": "Neste estacionamento cabem {capacity:cargo_bike} bicicletas de carga" + "pt": "Neste estacionamento cabem {capacity:cargo_bike} bicicletas de carga", + "es": "En este aparcamiento caben {capacity:cargo_bike} bicis de carga" }, "condition": "cargo_bike~designated|yes", "freeform": { @@ -579,6 +619,8 @@ ], "description": { "en": "A layer showing where you can park your bike", - "nl": "Een laag die toont waar je je fiets kunt parkeren" + "nl": "Een laag die toont waar je je fiets kunt parkeren", + "de": "Eine Ebene, die anzeigt, wo Sie Ihr Fahrrad abstellen können", + "es": "Una capa que muestra donde puedes aparcar tu bici" } } \ No newline at end of file diff --git a/assets/layers/bike_repair_station/bike_repair_station.json b/assets/layers/bike_repair_station/bike_repair_station.json index f7a39dc69..4b4ed274d 100644 --- a/assets/layers/bike_repair_station/bike_repair_station.json +++ b/assets/layers/bike_repair_station/bike_repair_station.json @@ -8,7 +8,8 @@ "de": "Fahrradstationen (Reparatur, Pumpe oder beides)", "it": "Stazioni bici (riparazione, gonfiaggio o entrambi)", "pt_BR": "Estações de bicicletas (reparo, bomba ou ambos)", - "ru": "Велостанции (ремонт, накачка шин или сразу всё)" + "ru": "Велостанции (ремонт, накачка шин или сразу всё)", + "es": "Bomba y reparación de bicicletas" }, "minzoom": 13, "source": { @@ -27,7 +28,8 @@ "de": "Fahrradstation (Pumpe & Reparatur)", "it": "Stazione bici (gonfiaggio & riparazione)", "pt_BR": "Estação de bicicletas (bomba e reparo)", - "ru": "Велостанция (накачка шин и ремонт)" + "ru": "Велостанция (накачка шин и ремонт)", + "es": "Estación de bicis (bomba y reparación)" }, "mappings": [ { @@ -46,7 +48,8 @@ "it": "Stazione riparazione bici", "pt_BR": "Estação de reparo de bicicletas", "pt": "Estação de reparo de bicicletas", - "ru": "Станция обслуживания велосипедов" + "ru": "Станция обслуживания велосипедов", + "es": "Estación de reparación de bicis" } }, { @@ -65,7 +68,8 @@ "it": "Stazione riparazione bici", "pt_BR": "Estação de reparo de bicicletas", "pt": "Estação de reparo de bicicletas", - "ru": "Станция обслуживания велосипедов" + "ru": "Станция обслуживания велосипедов", + "es": "Estación de reparación de bicis" } }, { @@ -88,7 +92,9 @@ "de": "Kaputte Pumpe", "it": "Pompa rotta", "ru": "Насос сломан", - "pt_BR": "Bomba quebrada" + "pt_BR": "Bomba quebrada", + "ca": "Bomba trencada", + "es": "Bomba rota" } }, { @@ -107,7 +113,8 @@ "de": "Fahrradpumpe {name}", "it": "Pompa per bici {name}", "ru": "Велосипедный насос {name}", - "pt_BR": "Bomba de bicicleta {name}" + "pt_BR": "Bomba de bicicleta {name}", + "es": "Bomba de bicicletas {name}" } }, { @@ -125,7 +132,9 @@ "de": "Fahrradpumpe", "it": "Pompa per bici", "ru": "Велосипедный насос", - "pt_BR": "Bomba de bicicleta" + "pt_BR": "Bomba de bicicleta", + "ca": "Bomba de bicicleta", + "es": "Bomba para bicicletas" } } ] @@ -149,7 +158,8 @@ "de": "Welche Einrichtungen stehen an dieser Fahrradstation zur Verfügung?", "it": "Quali servizi sono disponibili in questa stazione per bici?", "pt_BR": "Quais serviços estão disponíveis nesta estação de bicicletas?", - "pt": "Quais serviços estão disponíveis nesta estação de bicicletas?" + "pt": "Quais serviços estão disponíveis nesta estação de bicicletas?", + "es": "¿Qué servicios están disponibles en esta localización?" }, "mappings": [ { @@ -167,7 +177,8 @@ "de": "Es ist nur eine Pumpe vorhanden", "it": "C’è solamente una pompa presente", "pt_BR": "Há somente uma bomba presente", - "pt": "Há somente uma bomba presente" + "pt": "Há somente uma bomba presente", + "es": "Solo hay una bomba presente" } }, { @@ -185,7 +196,8 @@ "de": "Es sind nur Werkzeuge (Schraubenzieher, Zangen...) vorhanden", "it": "Ci sono solo degli attrezzi (cacciaviti, pinze…) presenti", "pt_BR": "Há somente ferramentas (chaves de fenda, alicates...) presentes", - "pt": "Há somente ferramentas (chaves de fenda, alicates...) presentes" + "pt": "Há somente ferramentas (chaves de fenda, alicates...) presentes", + "es": "Solo hay herramientas (destornilladores, pinzas...) presentes" } }, { @@ -203,7 +215,8 @@ "de": "Es sind sowohl Werkzeuge als auch eine Pumpe vorhanden", "it": "Ci sono sia attrezzi che pompa presenti", "pt_BR": "Há tanto ferramentas e uma bomba presente", - "pt": "Há tanto ferramentas e uma bomba presente" + "pt": "Há tanto ferramentas e uma bomba presente", + "es": "Hay tanto herramientas como bombas" } } ] @@ -217,7 +230,8 @@ "de": "Ist die Fahrradpumpe noch funktionstüchtig?", "it": "La pompa per bici è sempre funzionante?", "ru": "Велосипедный насос все еще работает?", - "pl": "Czy pompka rowerowa jest nadal sprawna?" + "pl": "Czy pompka rowerowa jest nadal sprawna?", + "es": "¿Todavía está operativa la bomba de bicicletas?" }, "condition": "service:bicycle:pump=yes", "mappings": [ @@ -231,7 +245,8 @@ "de": "Die Fahrradpumpe ist kaputt", "it": "La pompa per bici è guasta", "ru": "Велосипедный насос сломан", - "pl": "Pompka rowerowa jest zepsuta" + "pl": "Pompka rowerowa jest zepsuta", + "es": "La bomba de bicicletas está rota" } }, { @@ -244,7 +259,8 @@ "de": "Die Fahrradpumpe ist betriebsbereit", "it": "La pompa per bici funziona", "ru": "Велосипедный насос работает", - "pl": "Pompka rowerowa jest sprawna" + "pl": "Pompka rowerowa jest sprawna", + "es": "La bomba de bicicletas está operativa" } } ], @@ -257,7 +273,8 @@ "fr": "Quand ce point de réparation de vélo est-il ouvert ?", "it": "Quando è aperto questo punto riparazione bici?", "de": "Wann ist diese Fahrradreparaturstelle geöffnet?", - "ru": "Когда работает эта точка обслуживания велосипедов?" + "ru": "Когда работает эта точка обслуживания велосипедов?", + "es": "¿Cuándo está abierto este punto de reparación de bicicletas?" }, "render": "{opening_hours_table()}", "freeform": { @@ -275,7 +292,9 @@ "de": "Immer geöffnet", "ru": "Всегда открыто", "pt_BR": "Sempre aberto", - "pt": "Sempre aberto" + "pt": "Sempre aberto", + "ca": "Sempre obert", + "es": "Siempre abierto" } } ], @@ -285,21 +304,27 @@ "id": "access", "question": { "en": "Who is allowed to use this repair station?", - "nl": "Wie kan dit herstelpunt gebruiken?" + "nl": "Wie kan dit herstelpunt gebruiken?", + "de": "Wer darf diese Reparaturstation benutzen?", + "es": "¿A quién se le permite utilizar esta estación de reparación?" }, "mappings": [ { "if": "access=yes", "then": { "en": "Publicly accessible", - "nl": "Publiek toegankelijk" + "nl": "Publiek toegankelijk", + "de": "Öffentlich zugänglich", + "es": "Accesible públicamente" } }, { "if": "access=public", "then": { "en": "Publicly accessible", - "nl": "Publiek toegankelijk" + "nl": "Publiek toegankelijk", + "de": "Öffentlich zugänglich", + "es": "Accesible públicamente" }, "hideInAnswer": true }, @@ -307,14 +332,18 @@ "if": "access=customers", "then": { "en": "Only for customers", - "nl": "Enkel voor klanten van de bijhorende zaak" + "nl": "Enkel voor klanten van de bijhorende zaak", + "de": "Nur für Kunden", + "es": "Solo para clientes" } }, { "if": "access=private", "then": { "en": "Not accessible to the general public", - "nl": "Niet publiek toegankelijk" + "nl": "Niet publiek toegankelijk", + "de": "Nicht für die Allgemeinheit zugänglich", + "es": "No accesible para el público general" }, "icon": "./assets/svg/invalid.svg" }, @@ -322,7 +351,9 @@ "if": "access=no", "then": { "en": "Not accessible to the general public", - "nl": "Niet publiek toegankelijk" + "nl": "Niet publiek toegankelijk", + "de": "Nicht für die Allgemeinheit zugänglich", + "es": "No accesible para el público general" }, "icon": "./assets/svg/invalid.svg", "hideInAnswer": true @@ -340,7 +371,8 @@ "it": "Chi gestisce questa pompa per bici?", "de": "Wer wartet diese Fahrradpumpe?", "pt_BR": "Quem faz a manutenção desta bomba de ciclo?", - "pt": "Quem faz a manutenção desta bomba de ciclo?" + "pt": "Quem faz a manutenção desta bomba de ciclo?", + "es": "¿Quién mantiene esta bomba para bicicletas?" }, "render": { "nl": "Beheer door {operator}", @@ -349,7 +381,8 @@ "it": "Manutenuta da {operator}", "de": "Gewartet von {operator}", "pt_BR": "Mantida por {operator}", - "pt": "Mantida por {operator}" + "pt": "Mantida por {operator}", + "es": "Mantenido por {operator}" }, "freeform": { "key": "operator" @@ -364,7 +397,8 @@ "en": "What is the email address of the maintainer?", "nl": "Wat is het email-adres van de beheerder?", "de": "Wie lautet die E-Mail-Adresse des Betreuers?", - "fr": "Quelle est l'adresse email du service de maintenance ?" + "fr": "Quelle est l'adresse email du service de maintenance ?", + "es": "¿Es esta la dirección de correo electrónico del mantenedor?" }, "freeform": { "key": "email", @@ -381,7 +415,8 @@ "en": "What is the phone number of the maintainer?", "nl": "Wat is het telefoonnummer van de beheerder?", "de": "Wie lautet die Telefonnummer des Betreibers?", - "fr": "Quel est le numéro de téléphone du service de maintenance ?" + "fr": "Quel est le numéro de téléphone du service de maintenance ?", + "es": "¿Cual es el número de teléfono del mantenedor?" }, "freeform": { "key": "phone", @@ -398,7 +433,8 @@ "fr": "Est-ce que cette station vélo a un outil specifique pour réparer la chaîne du vélo ?", "gl": "Esta estación de arranxo de bicicletas ten unha ferramenta especial para arranxar a cadea da túa bicicleta?", "de": "Verfügt diese Fahrrad-Reparaturstation über Spezialwerkzeug zur Reparatur von Fahrradketten?", - "it": "Questa stazione di riparazione bici ha un attrezzo speciale per riparare la catena della bici?" + "it": "Questa stazione di riparazione bici ha un attrezzo speciale per riparare la catena della bici?", + "es": "¿Esta estación de reparación tiene una herramienta especial para reparar la cadena de tu bici?" }, "condition": "service:bicycle:tools=yes", "mappings": [ @@ -412,7 +448,8 @@ "de": "Es gibt ein Kettenwerkzeug", "it": "È presente un utensile per riparare la catena", "pt_BR": "Há uma ferramenta de corrente", - "pt": "Há uma ferramenta de corrente" + "pt": "Há uma ferramenta de corrente", + "es": "Hay una herramienta de cadenas" } }, { @@ -425,7 +462,8 @@ "de": "Es gibt kein Kettenwerkzeug", "it": "Non è presente un utensile per riparare la catena", "pt_BR": "Não há uma ferramenta de corrente", - "pt": "Não há uma ferramenta de corrente" + "pt": "Não há uma ferramenta de corrente", + "es": "No hay herramienta de cadenas" } } ] @@ -438,7 +476,8 @@ "fr": "Est-ce que cette station vélo à un crochet pour suspendre son vélo ou une accroche pour l'élevé ?", "gl": "Esta estación de bicicletas ten un guindastre para pendurar a túa bicicleta ou un soporte para elevala?", "de": "Hat diese Fahrradstation einen Haken, an dem Sie Ihr Fahrrad aufhängen können, oder einen Ständer, um es anzuheben?", - "it": "Questa stazione bici ha un gancio per tenere sospesa la bici o un supporto per alzarla?" + "it": "Questa stazione bici ha un gancio per tenere sospesa la bici o un supporto per alzarla?", + "es": "¿Esta estación tiene un gancho para colgar tu bici o un soporte para elevarla?" }, "condition": "service:bicycle:tools=yes", "mappings": [ @@ -452,7 +491,8 @@ "de": "Es gibt einen Haken oder Ständer", "it": "C’è un gancio o un supporto", "pt_BR": "Há um gancho ou um suporte", - "pt": "Há um gancho ou um suporte" + "pt": "Há um gancho ou um suporte", + "es": "Hay un gancho o soporte" } }, { @@ -465,7 +505,8 @@ "de": "Es gibt keinen Haken oder Ständer", "it": "Non c’è né un gancio né un supporto", "pt_BR": "Não há um gancho ou um suporte", - "pt": "Não há um gancho ou um suporte" + "pt": "Não há um gancho ou um suporte", + "es": "No hay ningún gancho o soporte" } } ] @@ -492,7 +533,8 @@ "gl": "Que válvulas son compatíbeis?", "de": "Welche Ventile werden unterstützt?", "it": "Quali valvole sono supportate?", - "pl": "Jakie zawory są obsługiwane?" + "pl": "Jakie zawory są obsługiwane?", + "es": "¿Que válvulas se soportan?" }, "render": { "en": "This pump supports the following valves: {valves}", @@ -502,7 +544,8 @@ "de": "Diese Pumpe unterstützt die folgenden Ventile: {valves}", "it": "Questa pompa è compatibile con le seguenti valvole: {valves}", "ru": "Этот насос поддерживает следующие клапаны: {valves}", - "pl": "Ta pompka obsługuje następujące zawory: {valves}" + "pl": "Ta pompka obsługuje następujące zawory: {valves}", + "es": "Esta bomba soporta las siguiente válvulas: {valves}" }, "freeform": { "#addExtraTags": [ @@ -560,7 +603,8 @@ "de": "Ist dies eine elektrische Fahrradpumpe?", "it": "Questa pompa per bici è elettrica?", "ru": "Это электрический велосипедный насос?", - "pl": "Czy jest to elektryczna pompka do roweru?" + "pl": "Czy jest to elektryczna pompka do roweru?", + "es": "¿Hay una bomba eléctrica para bicis?" }, "condition": "service:bicycle:pump=yes", "mappings": [ @@ -576,7 +620,9 @@ "ru": "Ручной насос", "pl": "Pompa ręczna", "pt_BR": "Bomba manual", - "pt": "Bomba manual" + "pt": "Bomba manual", + "ca": "Bomba manual", + "es": "Bomba manual" } }, { @@ -591,7 +637,9 @@ "ru": "Электрический насос", "pl": "Pompka elektryczna", "pt_BR": "Bomba elétrica", - "pt": "Bomba elétrica" + "pt": "Bomba elétrica", + "ca": "Bomba elèctrica", + "es": "Bomba eléctrica" } } ] @@ -605,7 +653,8 @@ "gl": "Ten a bomba de ar un indicador de presión ou un manómetro?", "de": "Verfügt die Pumpe über einen Druckanzeiger oder ein Manometer?", "it": "Questa pompa ha l’indicatore della pressione o il manometro?", - "pl": "Czy pompka posiada wskaźnik ciśnienia lub manometr?" + "pl": "Czy pompka posiada wskaźnik ciśnienia lub manometr?", + "es": "¿La bomba tiene un indicador de presión o manómetro?" }, "condition": "service:bicycle:pump=yes", "mappings": [ @@ -621,7 +670,8 @@ "ru": "Есть манометр", "pl": "Jest manometr", "pt_BR": "Há um manômetro", - "pt": "Há um manômetro" + "pt": "Há um manômetro", + "es": "Hay un manómetro" } }, { @@ -636,7 +686,8 @@ "ru": "Нет манометра", "pl": "Nie ma manometru", "pt_BR": "Não há um manômetro", - "pt": "Não há um manômetro" + "pt": "Não há um manômetro", + "es": "No hay ningún manometro" } }, { @@ -651,7 +702,8 @@ "ru": "Есть манометр, но он сломан", "pl": "Jest manometr, ale jest uszkodzony", "pt_BR": "Há um manômetro mas está quebrado", - "pt": "Há um manômetro mas está quebrado" + "pt": "Há um manômetro mas está quebrado", + "es": "Hay un manómetro pero está roto" } } ] @@ -670,7 +722,8 @@ "ru": "bелосипедный насос", "fi": "pyöräpumppu", "pl": "pompka do roweru", - "pt_BR": "uma bomba de bicicleta" + "pt_BR": "uma bomba de bicicleta", + "es": "una bomba de bicicletas" }, "tags": [ "amenity=bicycle_repair_station", @@ -685,7 +738,8 @@ "de": "Ein Gerät zum Aufpumpen von Reifen an einem festen Standort im öffentlichen Raum.", "pl": "Urządzenie do pompowania opon w stałym miejscu w przestrzeni publicznej.", "pt_BR": "Um dispositivo para encher seus pneus em um local fixa no espaço público", - "pt": "Um aparelho para encher os seus pneus num local fixa no espaço público" + "pt": "Um aparelho para encher os seus pneus num local fixa no espaço público", + "es": "Un dispositivo para inflar tus ruedas en una posición fija en el espacio público." }, "exampleImages": [ "./assets/layers/bike_repair_station/pump_example_round.jpg", @@ -701,7 +755,8 @@ "gl": "estación de arranxo de bicicletas con bomba de ar", "de": "eine fahrrad-reparaturstation und pumpe", "it": "una stazione di riparazione bici e pompa", - "pl": "stacja naprawy rowerów i pompka" + "pl": "stacja naprawy rowerów i pompka", + "es": "En estación de reparación de bicicletas y bomba" }, "tags": [ "amenity=bicycle_repair_station", @@ -713,7 +768,8 @@ "nl": "Een fietspomp en gereedschap om je fiets te herstellen in de publieke ruimte. Deze zijn op een vastgemaakt, bijvoorbeeld aan een paal.", "fr": "Un dispositif avec des outils pour réparer votre vélo combiné à une pompe a un emplacement fixe. Les outils sont souvent attachés par une chaîne pour empêcher le vol.", "it": "Un dispositivo con attrezzi per riparare la tua bici e una pompa in un luogo fisso. Gli attrezzi sono spesso attaccati ad una catena per prevenire il furto.", - "de": "Ein Gerät mit Werkzeugen zur Reparatur von Fahrrädern kombiniert mit einer Pumpe an einem festen Standort. Die Werkzeuge sind oft mit Ketten gegen Diebstahl gesichert." + "de": "Ein Gerät mit Werkzeugen zur Reparatur von Fahrrädern kombiniert mit einer Pumpe an einem festen Standort. Die Werkzeuge sind oft mit Ketten gegen Diebstahl gesichert.", + "es": "Una bomba de bicicletas y herramientas para reparar tu bicicleta en el espacio público. Las herramientas habitualmente están aseguradas con cadenas contra el robo." }, "exampleImages": [ "./assets/layers/bike_repair_station/repair_station_example_2.jpg", @@ -728,7 +784,8 @@ "gl": "estación de arranxo de bicicletas sin bomba de ar", "de": "eine fahrrad-reparaturstation ohne pumpe", "it": "una stazione di riparazione bici senza pompa", - "ru": "Станция обслуживания велосипедов без накачки (насоса)" + "ru": "Станция обслуживания велосипедов без накачки (насоса)", + "es": "una estación de reparación de bicicletas sin bomba" }, "tags": [ "amenity=bicycle_repair_station", @@ -737,7 +794,9 @@ ], "description": { "en": "Tools to repair your bike in the public space (without pump). The tools are secured against theft.", - "nl": "Gereedschap om je fiets te herstellen in de publieke ruimte (zonder pomp). Deze zijn op een vastgemaakt, bijvoorbeeld aan een paal." + "nl": "Gereedschap om je fiets te herstellen in de publieke ruimte (zonder pomp). Deze zijn op een vastgemaakt, bijvoorbeeld aan een paal.", + "de": "Werkzeug, um Ihr Fahrrad im öffentlichen Raum zu reparieren (ohne Pumpe). Die Werkzeuge sind gegen Diebstahl gesichert.", + "es": "Herramientas para reparar tu bici en el espacio público (sin bomba).Las herramientas están aseguradas contra el robo." } } ], @@ -829,6 +888,8 @@ ], "description": { "en": "A layer showing bicycle pumps and bicycle repair tool stands", - "nl": "Deze laag toont fietspompen en herstelpunten voor fietsen" + "nl": "Deze laag toont fietspompen en herstelpunten voor fietsen", + "de": "Eine Ebene mit Fahrradpumpen und Werkzeugständern für die Fahrradreparatur", + "es": "Una capa que muestra bombas de bicicletas y puestos de herramientas de reparación de bicicletas" } } \ No newline at end of file diff --git a/assets/layers/bike_shop/bike_shop.json b/assets/layers/bike_shop/bike_shop.json index 09a66e97e..2b5c11a01 100644 --- a/assets/layers/bike_shop/bike_shop.json +++ b/assets/layers/bike_shop/bike_shop.json @@ -9,7 +9,8 @@ "it": "Venditore/riparatore bici", "ru": "Обслуживание велосипедов/магазин", "pt_BR": "Reparo/loja de bicicletas", - "pt": "Reparo/loja de bicicletas" + "pt": "Reparo/loja de bicicletas", + "ca": "Botiga/reparació de bicicletes" }, "minzoom": 13, "allowMove": true, @@ -54,7 +55,8 @@ "it": "Venditore/riparatore bici", "ru": "Обслуживание велосипедов/магазин", "pt_BR": "Reparo/loja de bicicletas", - "pt": "Reparo/loja de bicicletas" + "pt": "Reparo/loja de bicicletas", + "ca": "Botiga/reparació de bicicletes" }, "mappings": [ { @@ -102,7 +104,8 @@ "ru": "Прокат велосипедов {name}", "de": "Fahrradverleih{name}", "pt_BR": "Aluguel de bicicletas {name}", - "pt": "Aluguel de bicicletas {name}" + "pt": "Aluguel de bicicletas {name}", + "es": "Alquiler de bicicletas {name}" } }, { @@ -121,7 +124,8 @@ "it": "Riparazione biciclette {name}", "ru": "Ремонт велосипедов {name}", "pt_BR": "Reparo de bicicletas {name}", - "pt": "Reparo de bicicletas {name}" + "pt": "Reparo de bicicletas {name}", + "es": "Reparación de bicis {name}" } }, { @@ -139,7 +143,8 @@ "it": "Negozio di biciclette {name}", "ru": "Магазин велосипедов {name}", "pt_BR": "Loja de bicicletas {name}", - "pt": "Loja de bicicletas {name}" + "pt": "Loja de bicicletas {name}", + "es": "Tienda de bicis {name}" } }, { @@ -189,7 +194,8 @@ "ru": "Магазин, специализирующийся на продаже велосипедов или сопутствующих товаров", "pt_BR": "Uma loja que vende especificamente bicicletas ou itens relacionados", "de": "Ein Geschäft, das speziell Fahrräder oder verwandte Artikel verkauft", - "pt": "Uma loja que vende especificamente bicicletas ou itens relacionados" + "pt": "Uma loja que vende especificamente bicicletas ou itens relacionados", + "es": "Una tiene que vende específicamente bicis u objetos relacionados" }, "tagRenderings": [ "images", @@ -209,14 +215,16 @@ "it": "Questo negozio è specializzato nella vendita di {shop} ed effettua attività relative alle biciclette", "pt_BR": "Esta loja é especializada em vender {shop} e faz atividades relacionadas à bicicletas", "de": "Dieses Geschäft ist auf den Verkauf von {shop} spezialisiert und im Bereich Fahrrad tätig", - "pt": "Esta loja é especializada em vender {shop} e faz atividades relacionadas à bicicletas" + "pt": "Esta loja é especializada em vender {shop} e faz atividades relacionadas à bicicletas", + "es": "Esta tienda está especializada en vender {shop} y hace actividades relacionadas con bicicletas" }, "mappings": [ { "if": "shop=rental", "then": { "nl": "Deze zaak focust op verhuur", - "en": "Deze business focuses on rental" + "en": "Deze business focuses on rental", + "de": "Dieses Geschäft konzentriert sich auf die Vermietung" } } ] @@ -231,7 +239,8 @@ "it": "Qual è il nome di questo negozio di biciclette?", "ru": "Как называется магазин велосипедов?", "pt_BR": "Qual o nome desta loja de bicicletas?", - "pt": "Qual o nome desta loja de bicicletas?" + "pt": "Qual o nome desta loja de bicicletas?", + "es": "¿Cual es el nombre de esta tienda de bicicletas?" }, "render": { "en": "This bicycle shop is called {name}", @@ -242,7 +251,8 @@ "it": "Questo negozio di biciclette è chiamato {name}", "ru": "Этот магазин велосипедов называется {name}", "pt_BR": "Esta loja de bicicletas se chama {name}", - "pt": "Esta loja de bicicletas se chama {name}" + "pt": "Esta loja de bicicletas se chama {name}", + "es": "Esta tienda de bicicletas se llama {name}" }, "freeform": { "key": "name" @@ -260,7 +270,8 @@ "id": "URL {name} apa?", "de": "Was ist die Webseite von {name}?", "pt_BR": "Qual o website de {name}?", - "pt": "Qual o website de {name}?" + "pt": "Qual o website de {name}?", + "es": "¿Cual es el sitio web de {name}?" }, "render": "{website}", "freeform": { @@ -279,7 +290,8 @@ "ru": "Какой номер телефона у {name}?", "de": "Wie lautet die Telefonnummer von {name}?", "pt_BR": "Qual o número de telefone de {name}?", - "pt": "Qual é o número de telefone de {name}?" + "pt": "Qual é o número de telefone de {name}?", + "es": "¿Cual es el número de teléfono de {name}?" }, "render": "{phone}", "freeform": { @@ -298,7 +310,8 @@ "ru": "Какой адрес электронной почты у {name}?", "de": "Wie lautet die E-Mail-Adresse von {name}?", "pt_BR": "Qual o endereço de email de {name}?", - "pt": "Qual o endereço de email de {name}?" + "pt": "Qual o endereço de email de {name}?", + "es": "¿Cual es la dirección de correo electrónico de {name}?" }, "render": "{email}", "freeform": { @@ -311,7 +324,9 @@ { "render": { "en": "Only accessible to {access}", - "nl": "Enkel voor {access}" + "nl": "Enkel voor {access}", + "de": "Nur zugänglich für {access}", + "es": "Solo accesible a {access}" }, "freeform": { "key": "access" @@ -329,7 +344,8 @@ "it": "Questo negozio vende bici?", "ru": "Продаются ли велосипеды в этом магазине?", "pt_BR": "Esta loja vende bicicletas?", - "pt": "Esta loja vende bicicletas?" + "pt": "Esta loja vende bicicletas?", + "es": "¿Vende bicis esta tienda?" }, "mappings": [ { @@ -343,7 +359,8 @@ "it": "Questo negozio vende bici", "ru": "В этом магазине продаются велосипеды", "pt_BR": "Esta loja vende bicicletas", - "pt": "Esta loja vende bicicletas" + "pt": "Esta loja vende bicicletas", + "es": "Esta tienda vende bicis" } }, { @@ -357,7 +374,8 @@ "it": "Questo negozio non vende bici", "ru": "В этом магазине не продают велосипеды", "pt_BR": "Esta loja não vende bicicletas", - "pt": "Esta loja não vende bicicletas" + "pt": "Esta loja não vende bicicletas", + "es": "Esta tienda no vende bicis" } } ] @@ -373,7 +391,8 @@ "it": "Questo negozio ripara bici?", "ru": "В этом магазине ремонтируют велосипеды?", "pt_BR": "Esta loja conserta bicicletas?", - "pt": "Esta loja conserta bicicletas?" + "pt": "Esta loja conserta bicicletas?", + "es": "¿Repara bicis esta tienda?" }, "mappings": [ { @@ -387,7 +406,8 @@ "it": "Questo negozio ripara bici", "ru": "Этот магазин ремонтирует велосипеды", "pt_BR": "Esta loja conserta bicicletas", - "pt": "Esta loja conserta bicicletas" + "pt": "Esta loja conserta bicicletas", + "es": "Esta tienda repara bicis" } }, { @@ -401,7 +421,8 @@ "it": "Questo negozio non ripara bici", "ru": "Этот магазин не ремонтирует велосипеды", "pt_BR": "Esta loja não conserta bicicletas", - "pt": "Esta loja não conserta bicicletas" + "pt": "Esta loja não conserta bicicletas", + "es": "Esta tienda no repara bicis" } }, { @@ -415,7 +436,8 @@ "it": "Questo negozio ripara solo le bici che sono state acquistate qua", "ru": "Этот магазин ремонтирует только велосипеды, купленные здесь", "pt_BR": "Esta loja conserta bicicletas compradas aqui", - "pt": "Esta loja conserta bicicletas compradas aqui" + "pt": "Esta loja conserta bicicletas compradas aqui", + "es": "Esta tienda solo repara bicis compradas aquí" } }, { @@ -429,7 +451,8 @@ "it": "Questo negozio ripara solo le biciclette di una certa marca", "ru": "В этом магазине обслуживают велосипеды определённого бренда", "pt_BR": "Esta loja conserta bicicletas de uma certa marca", - "pt": "Esta loja conserta bicicletas de uma certa marca" + "pt": "Esta loja conserta bicicletas de uma certa marca", + "es": "Esta tienda solo repara bicis de una cierta marca" } } ] @@ -446,7 +469,8 @@ "it": "Questo negozio noleggia le bici?", "ru": "Этот магазин сдает велосипеды в аренду?", "pt_BR": "Esta loja aluga bicicletas?", - "pt": "Esta loja aluga bicicletas?" + "pt": "Esta loja aluga bicicletas?", + "es": "¿Alquila bicicis esta tienda?" }, "mappings": [ { @@ -460,7 +484,8 @@ "it": "Questo negozio noleggia le bici", "ru": "Этот магазин сдает велосипеды в аренду", "pt_BR": "Esta loja aluga bicicletas", - "pt": "Esta loja aluga bicicletas" + "pt": "Esta loja aluga bicicletas", + "es": "Esta tienda alquila bicis" } }, { @@ -474,7 +499,8 @@ "it": "Questo negozio non noleggia le bici", "ru": "Этот магазин не сдает велосипеды напрокат", "pt_BR": "Esta loja não aluga bicicletas", - "pt": "Esta loja não aluga bicicletas" + "pt": "Esta loja não aluga bicicletas", + "es": "Esta tienda no alquila bicis" } } ] @@ -489,7 +515,8 @@ "gl": "Esta tenda vende bicicletas de segunda man?", "de": "Verkauft dieses Geschäft gebrauchte Fahrräder?", "it": "Questo negozio vende bici usate?", - "ru": "В этом магазине продаются подержанные велосипеды?" + "ru": "В этом магазине продаются подержанные велосипеды?", + "es": "¿Vende bicis de segunda mano esta tienda?" }, "mappings": [ { @@ -501,7 +528,8 @@ "gl": "Esta tenda vende bicicletas de segunda man", "de": "Dieses Geschäft verkauft gebrauchte Fahrräder", "it": "Questo negozio vende bici usate", - "ru": "В этом магазине продаются подержанные велосипеды" + "ru": "В этом магазине продаются подержанные велосипеды", + "es": "Esta tienda vende bicis de segunda mano" } }, { @@ -513,7 +541,8 @@ "gl": "Esta tenda non vende bicicletas de segunda man", "de": "Dieses Geschäft verkauft keine gebrauchten Fahrräder", "it": "Questo negozio non vende bici usate", - "ru": "В этом магазине не продаются подержанные велосипеды" + "ru": "В этом магазине не продаются подержанные велосипеды", + "es": "Esta tienda no vende bicis de segunda mano" } }, { @@ -525,7 +554,8 @@ "gl": "Esta tenda só vende bicicletas de segunda man", "de": "Dieses Geschäft verkauft nur gebrauchte Fahrräder", "it": "Questo negozio vende solamente bici usate", - "ru": "В этом магазине продаются только подержанные велосипеды" + "ru": "В этом магазине продаются только подержанные велосипеды", + "es": "Esta tienda solo vende bicis de segunda mano" } } ] @@ -539,7 +569,8 @@ "gl": "Esta tenda ofrece unha bomba de ar para uso de calquera persoa?", "de": "Bietet dieses Geschäft eine Fahrradpumpe zur Benutzung für alle an?", "it": "Questo negozio offre l’uso a chiunque di una pompa per bici?", - "ru": "Предлагается ли в этом магазине велосипедный насос для всеобщего пользования?" + "ru": "Предлагается ли в этом магазине велосипедный насос для всеобщего пользования?", + "es": "¿Esta tienda ofrece una bomba para que la utilice cualquiera?" }, "mappings": [ { @@ -551,7 +582,8 @@ "gl": "Esta tenda ofrece unha bomba de ar para uso de calquera persoa", "de": "Dieses Geschäft bietet eine Fahrradpumpe für alle an", "it": "Questo negozio offre l’uso pubblico di una pompa per bici", - "ru": "В этом магазине есть велосипедный насос для всеобщего пользования" + "ru": "В этом магазине есть велосипедный насос для всеобщего пользования", + "es": "Esta tienda ofrece una bomba para cualquiera" } }, { @@ -563,7 +595,8 @@ "gl": "Esta tenda non ofrece unha bomba de ar para uso de calquera persoa", "de": "Dieses Geschäft bietet für niemanden eine Fahrradpumpe an", "it": "Questo negozio non offre l’uso pubblico di una pompa per bici", - "ru": "В этом магазине нет велосипедного насоса для всеобщего пользования" + "ru": "В этом магазине нет велосипедного насоса для всеобщего пользования", + "es": "Esta tienda no ofrece una bomba para cualquiera" } }, { @@ -573,7 +606,8 @@ "nl": "Er is een fietspomp, deze is apart aangeduid", "fr": "Il y a une pompe à vélo, c'est indiqué comme un point séparé ", "it": "C’è una pompa per bici, è mostrata come punto separato ", - "de": "Es gibt eine Fahrradpumpe, sie wird als separater Punkt angezeigt " + "de": "Es gibt eine Fahrradpumpe, sie wird als separater Punkt angezeigt ", + "es": "Hay una bomba para bicicletas, se muestra como un punto separado " } } ] @@ -587,7 +621,8 @@ "gl": "Hai ferramentas aquí para arranxar a túa propia bicicleta?", "de": "Gibt es hier Werkzeuge, um das eigene Fahrrad zu reparieren?", "it": "Sono presenti degli attrezzi per riparare la propria bici?", - "ru": "Есть ли здесь инструменты для починки собственного велосипеда?" + "ru": "Есть ли здесь инструменты для починки собственного велосипеда?", + "es": "¿Hay herramientas para reparar tu propia bici?" }, "mappings": [ { @@ -633,7 +668,8 @@ "fr": "Lave-t-on les vélos ici ?", "it": "Vengono lavate le bici qua?", "ru": "Здесь моют велосипеды?", - "de": "Werden hier Fahrräder gewaschen?" + "de": "Werden hier Fahrräder gewaschen?", + "es": "¿Aquí se lavan bicicletas?" }, "mappings": [ { @@ -644,7 +680,8 @@ "fr": "Ce magasin lave les vélos", "it": "Questo negozio lava le biciclette", "de": "Dieses Geschäft reinigt Fahrräder", - "ru": "В этом магазине оказываются услуги мойки/чистки велосипедов" + "ru": "В этом магазине оказываются услуги мойки/чистки велосипедов", + "es": "Esta tienda limpia bicicletas" } }, { @@ -654,7 +691,8 @@ "nl": "Deze winkel biedt een installatie aan om zelf je fiets schoon te maken", "fr": "Ce magasin a une installation pour laver soi même des vélos", "it": "Questo negozio ha una struttura dove è possibile pulire la propria bici", - "de": "Dieser Laden hat eine Anlage, in der man Fahrräder selbst reinigen kann" + "de": "Dieser Laden hat eine Anlage, in der man Fahrräder selbst reinigen kann", + "es": "Esta tienda tiene una instalación donde uno puede limpiar bicicletas por si mismo" } }, { @@ -665,7 +703,8 @@ "fr": "Ce magasin ne fait pas le nettoyage de vélo", "it": "Questo negozio non offre la pulizia della bicicletta", "de": "Dieser Laden bietet keine Fahrradreinigung an", - "ru": "В этом магазине нет услуг мойки/чистки велосипедов" + "ru": "В этом магазине нет услуг мойки/чистки велосипедов", + "es": "Esta tienda no ofrece limpieza de bicicletas" } } ] diff --git a/assets/layers/bike_themed_object/bike_themed_object.json b/assets/layers/bike_themed_object/bike_themed_object.json index c55f8d6cc..6c173061c 100644 --- a/assets/layers/bike_themed_object/bike_themed_object.json +++ b/assets/layers/bike_themed_object/bike_themed_object.json @@ -5,7 +5,8 @@ "nl": "Fietsgerelateerd object", "fr": "Objet cycliste", "de": "Weitere fahrradbezogene Objekte", - "it": "Oggetto relativo alle bici" + "it": "Oggetto relativo alle bici", + "es": "Objeto relacionada con bicis" }, "minzoom": 13, "source": { @@ -29,7 +30,8 @@ "nl": "Fietsgerelateerd object", "fr": "Objet cycliste", "de": "Mit Fahrrad zusammenhängendes Objekt", - "it": "Oggetto relativo alle bici" + "it": "Oggetto relativo alle bici", + "es": "Objeto relacionado con bicis" }, "mappings": [ { @@ -44,7 +46,9 @@ "fr": "Piste cyclable", "it": "Pista ciclabile", "de": "Radweg", - "ru": "Велотрек" + "ru": "Велотрек", + "ca": "Pista ciclable", + "es": "Carril bici" } } ] @@ -82,6 +86,8 @@ ], "description": { "en": "A layer with bike-themed objects but who don't match any other layer", - "nl": "Een laag met fietsgerelateerde diensten, die in geen enkele andere laag konden ondergebracht worden" + "nl": "Een laag met fietsgerelateerde diensten, die in geen enkele andere laag konden ondergebracht worden", + "de": "Eine Ebene mit Objekten zum Thema Fahrrad, die zu keiner anderen Ebene passen", + "es": "Una capa con los objetos relacionados con bicis pero que no coinciden con ninguna otra capa" } } \ No newline at end of file diff --git a/assets/layers/binocular/binocular.json b/assets/layers/binocular/binocular.json index 3ed6a4bed..8bdb07043 100644 --- a/assets/layers/binocular/binocular.json +++ b/assets/layers/binocular/binocular.json @@ -4,7 +4,8 @@ "en": "Binoculars", "nl": "Verrekijkers", "de": "Ferngläser", - "ru": "Бинокль" + "ru": "Бинокль", + "ca": "Prismàtics" }, "minzoom": 0, "title": { @@ -12,14 +13,17 @@ "en": "Binoculars", "nl": "Verrekijker", "de": "Ferngläser", - "ru": "Бинокль" + "ru": "Бинокль", + "ca": "Prismàtics", + "es": "Binoculares" } }, "description": { "en": "Binoculas", "nl": "Verrekijkers", "de": "Fernglas", - "ru": "Бинокли" + "ru": "Бинокли", + "ca": "Prismàtics" }, "tagRenderings": [ "images", @@ -48,12 +52,14 @@ "render": { "en": "Using these binoculars costs {charge}", "nl": "Deze verrekijker gebruiken kost {charge}", - "de": "Die Benutzung dieses Fernglases kostet {charge}" + "de": "Die Benutzung dieses Fernglases kostet {charge}", + "es": "Utilizar estos binoculares cuesta {charge}" }, "question": { "en": "How much does one have to pay to use these binoculars?", "nl": "Hoeveel moet men betalen om deze verrekijker te gebruiken?", - "de": "Wie viel muss man für die Nutzung dieser Ferngläser bezahlen?" + "de": "Wie viel muss man für die Nutzung dieser Ferngläser bezahlen?", + "es": "¿Cuánto hay que pagar para utilizar estos binoculares?" }, "id": "binocular-charge" }, @@ -61,12 +67,14 @@ "question": { "en": "When looking through this binocular, in what direction does one look?", "nl": "Welke richting kijkt men uit als men door deze verrekijker kijkt?", - "de": "In welche Richtung blickt man, wenn man durch dieses Fernglas schaut?" + "de": "In welche Richtung blickt man, wenn man durch dieses Fernglas schaut?", + "es": "¿Cuándo uno mira a través de este binocular, en qué dirección lo hace?" }, "render": { "en": "Looks towards {direction}°", "nl": "Kijkt richting {direction}°", - "de": "Blick in Richtung {direction}°" + "de": "Blick in Richtung {direction}°", + "es": "Mira hacia {direction}º" }, "freeform": { "key": "direction", @@ -84,7 +92,8 @@ "en": "a binoculars", "nl": "een verrekijker", "de": "eine ferngläser", - "ru": "бинокль" + "ru": "бинокль", + "ca": "uns prismàtics" }, "description": { "en": "A telescope or pair of binoculars mounted on a pole, available to the public to look around. ", diff --git a/assets/layers/birdhide/birdhide.json b/assets/layers/birdhide/birdhide.json index a026ff132..865815697 100644 --- a/assets/layers/birdhide/birdhide.json +++ b/assets/layers/birdhide/birdhide.json @@ -3,7 +3,8 @@ "name": { "en": "Bird watching places", "nl": "Vogelkijkhutten", - "de": "Orte zur Vogelbeobachtung" + "de": "Orte zur Vogelbeobachtung", + "es": "Lugares para ver pájaros" }, "minzoom": 14, "source": { @@ -142,7 +143,8 @@ }, "then": { "en": "There are special provisions for wheelchair users", - "nl": "Er zijn speciale voorzieningen voor rolstoelen" + "nl": "Er zijn speciale voorzieningen voor rolstoelen", + "es": "Hay provisiones especiales para usuarios de sillas de ruedas" } }, { @@ -175,7 +177,9 @@ }, "then": { "en": "Not accessible to wheelchair users", - "nl": "Niet rolstoeltoegankelijk" + "nl": "Niet rolstoeltoegankelijk", + "de": "Nicht zugänglich für Rollstuhlfahrer", + "es": "No accesible a usuarios con sillas de ruedas" } } ] @@ -183,7 +187,9 @@ { "render": { "en": "Operated by {operator}", - "nl": "Beheer door {operator}" + "nl": "Beheer door {operator}", + "de": "Betrieben von {operator}", + "es": "Operado por {operator}" }, "freeform": { "key": "operator" @@ -197,14 +203,17 @@ "if": "operator=Natuurpunt", "then": { "en": "Operated by Natuurpunt", - "nl": "Beheer door Natuurpunt" + "nl": "Beheer door Natuurpunt", + "de": "Betrieben von Natuurpunt", + "es": "Operado por Natuurpunt" } }, { "if": "operator=Agentschap Natuur en Bos", "then": { "en": "Operated by the Agency for Nature and Forests", - "nl": "Beheer door het Agentschap Natuur en Bos" + "nl": "Beheer door het Agentschap Natuur en Bos", + "de": "Betrieben von einer Forst- bzw. Naturschutzbehörde" } } ], @@ -239,7 +248,9 @@ }, "description": { "en": "A covered shelter where one can watch birds comfortably", - "nl": "Een overdekte hut waarbinnen er warm en droog naar vogels gekeken kan worden" + "nl": "Een overdekte hut waarbinnen er warm en droog naar vogels gekeken kan worden", + "de": "Ein überdachter Unterstand, in dem man bequem Vögel beobachten kann", + "es": "Un refugio cubierto donde se pueden ver pájaros confortablemente" } }, { @@ -254,7 +265,8 @@ }, "description": { "en": "A screen or wall with openings to watch birds", - "nl": "Een vogelkijkwand waarachter men kan staan om vogels te kijken" + "nl": "Een vogelkijkwand waarachter men kan staan om vogels te kijken", + "es": "Una pantalla o pared con aperturas para ver pájaros" } } ], @@ -267,7 +279,9 @@ "nl": "Rolstoeltoegankelijk", "en": "Wheelchair accessible", "de": "Zugänglich für Rollstuhlfahrer", - "fr": "Accessible aux fauteuils roulants" + "fr": "Accessible aux fauteuils roulants", + "ca": "Accessible per a cadires de rodes", + "es": "Accesible con sillas de ruedas" }, "osmTags": { "or": [ diff --git a/assets/layers/cafe_pub/cafe_pub.json b/assets/layers/cafe_pub/cafe_pub.json index 71f326721..42cd2ce79 100644 --- a/assets/layers/cafe_pub/cafe_pub.json +++ b/assets/layers/cafe_pub/cafe_pub.json @@ -6,7 +6,8 @@ "de": "Cafés und Kneipen", "fr": "Cafés et pubs", "zh_Hant": "咖啡廳與酒吧", - "hu": "Kávézók és kocsmák" + "hu": "Kávézók és kocsmák", + "es": "Cafeterías y bares" }, "source": { "osmTags": { @@ -28,11 +29,14 @@ "nl": "een bruin café of kroeg", "de": "eine kneipe", "ru": "паб", - "hu": "kocsma" + "hu": "kocsma", + "ca": "un bar" }, "description": { "en": "A pub, mostly for drinking beers in a warm, relaxed interior", - "nl": "Dit is een bruin café of een kroeg waar voornamelijk bier wordt gedronken. De inrichting is typisch gezellig met veel houtwerk" + "nl": "Dit is een bruin café of een kroeg waar voornamelijk bier wordt gedronken. De inrichting is typisch gezellig met veel houtwerk", + "de": "Eine Kneipe, in der vor allem Bier in ruhiger, entspannter Atmosphäre getrunken wird", + "es": "Un bar, principalmente para beber cervezas en un interior templado y relajado" }, "preciseInput": { "preferredBackground": "map" @@ -47,11 +51,13 @@ "nl": "een bar", "de": "eine bar", "ru": "бар", - "hu": "bár" + "hu": "bár", + "ca": "un pub" }, "description": { "en": "A more modern and commercial bar, possibly with a music and light installation", - "nl": "Dit is een bar waar men ter plaatse alcoholische drank nuttigt. De inrichting is typisch modern en commercieel, soms met lichtinstallatie en feestmuziek" + "nl": "Dit is een bar waar men ter plaatse alcoholische drank nuttigt. De inrichting is typisch modern en commercieel, soms met lichtinstallatie en feestmuziek", + "de": "Eine modernere und kommerzielle Bar, möglicherweise mit einer Musik- und Lichtinstallation" }, "preciseInput": { "preferredBackground": "map" @@ -66,11 +72,13 @@ "nl": "een café", "de": "eine café", "ru": "кафе", - "hu": "kávézó" + "hu": "kávézó", + "ca": "un cafè" }, "description": { "en": "A cafe to drink tea, coffee or an alcoholical bevarage in a quiet environment", - "nl": "Dit is een cafe - een plaats waar men rustig kan zitten om een thee, koffie of alcoholische drank te nuttigen." + "nl": "Dit is een cafe - een plaats waar men rustig kan zitten om een thee, koffie of alcoholische drank te nuttigen.", + "de": "Ein Café, um in ruhiger Umgebung Tee, Kaffee oder ein alkoholisches Getränk zu trinken" }, "preciseInput": { "preferredBackground": "map" @@ -80,7 +88,9 @@ "title": { "render": { "en": "Pub", - "nl": "Café" + "nl": "Café", + "ca": "Bar", + "de": "Kneipe" }, "mappings": [ { @@ -93,7 +103,8 @@ "nl": "{name}", "en": "{name}", "de": "{name}", - "ru": "{name}" + "ru": "{name}", + "ca": "{name}" } } ] @@ -132,35 +143,40 @@ "if": "amenity=pub", "then": { "en": "A pub, mostly for drinking beers in a warm, relaxed interior", - "nl": "Dit is een bruin café of een kroeg waar voornamelijk bier wordt gedronken. De inrichting is typisch gezellig met veel houtwerk" + "nl": "Dit is een bruin café of een kroeg waar voornamelijk bier wordt gedronken. De inrichting is typisch gezellig met veel houtwerk", + "de": "Eine Kneipe, in der vor allem Bier in ruhiger, entspannter Atmosphäre getrunken wird" } }, { "if": "amenity=bar", "then": { "en": "A more modern and commercial bar, possibly with a music and light installation", - "nl": "Dit is een bar waar men ter plaatse alcoholische drank nuttigt. De inrichting is typisch modern en commercieel, soms met lichtinstallatie en feestmuziek" + "nl": "Dit is een bar waar men ter plaatse alcoholische drank nuttigt. De inrichting is typisch modern en commercieel, soms met lichtinstallatie en feestmuziek", + "de": "Eine modernere und kommerzielle Bar, möglicherweise mit einer Musik- und Lichtinstallation" } }, { "if": "amenity=cafe", "then": { "en": "A cafe to drink tea, coffee or an alcoholical bevarage in a quiet environment", - "nl": "Dit is een cafe - een plaats waar men rustig kan zitten om een thee, koffie of alcoholische drank te nuttigen." + "nl": "Dit is een cafe - een plaats waar men rustig kan zitten om een thee, koffie of alcoholische drank te nuttigen.", + "de": "Ein Café, um in ruhiger Umgebung Tee, Kaffee oder ein alkoholisches Getränk zu trinken" } }, { "if": "amenity=restaurant", "then": { "en": "A restuarant where one can get a proper meal", - "nl": "Dit is een restaurant waar men een maaltijd geserveerd krijgt" + "nl": "Dit is een restaurant waar men een maaltijd geserveerd krijgt", + "de": "Ein Restaurant, in dem man ordentlich essen kann" } }, { "if": "amenity=biergarten", "then": { "en": "An open space where beer is served, typically seen in Germany", - "nl": "Een open ruimte waar bier geserveerd wordt. Typisch in Duitsland" + "nl": "Een open ruimte waar bier geserveerd wordt. Typisch in Duitsland", + "de": "Ein Außenbereich mit Bierausschank, typischerweise in Deutschland" }, "hideInAnswer": "_country!=de" } @@ -186,7 +202,9 @@ "nl": "Nu geopened", "de": "Derzeit geöffnet", "fr": "Ouvert maintenant", - "hu": "Most nyitva van" + "hu": "Most nyitva van", + "ca": "Obert ara", + "es": "Abiert oahora" }, "osmTags": "_isOpen=yes" } @@ -204,7 +222,9 @@ { "explanation": { "nl": "{title()} is permanent gestopt", - "en": "{title()} has closed down permanently" + "en": "{title()} has closed down permanently", + "de": "{title()} wurde dauerhaft geschlossen", + "es": "{title()} ha cerrado permanentemente" }, "changesetMessage": "shop_closed" } @@ -245,6 +265,8 @@ "description": { "en": "A layer showing cafés and pubs where one can gather around a drink. The layer asks for some relevant questions", "hu": "Egy olyan réteg, amely kávézókat és kocsmákat jelenít meg, ahol össze lehet gyűlni egy ital köré. A réteg néhány lényeges kérdést tesz fel", - "nl": "Een laag die kroegen en koffiehuizen toont waar je iets kunt drinken. De laag zal je enkele vragen stellen" + "nl": "Een laag die kroegen en koffiehuizen toont waar je iets kunt drinken. De laag zal je enkele vragen stellen", + "de": "Eine Ebene mit Cafés und Kneipen, in denen man sich auf ein Getränk treffen kann. Die Ebene fragt nach einigen relevanten Eigenschaften", + "es": "Una capa que muestra cafeterías y bares donde uno se puede reunir con una bebida. La capa pregunta algunas preguntas relevantes" } } \ No newline at end of file diff --git a/assets/layers/charging_station/charging_station.json b/assets/layers/charging_station/charging_station.json index 93b69c337..959c91114 100644 --- a/assets/layers/charging_station/charging_station.json +++ b/assets/layers/charging_station/charging_station.json @@ -3,7 +3,8 @@ "name": { "en": "Charging stations", "nl": "Oplaadpunten", - "de": "Ladestationen" + "de": "Ladestationen", + "ca": "Estacions de càrrega" }, "minzoom": 10, "source": { @@ -23,7 +24,8 @@ "title": { "render": { "en": "Charging station", - "nl": "Oplaadpunt" + "nl": "Oplaadpunt", + "ca": "Estació de càrrega" }, "mappings": [ { @@ -131,11 +133,13 @@ "id": "access", "question": { "en": "Who is allowed to use this charging station?", - "nl": "Wie mag er dit oplaadpunt gebruiken?" + "nl": "Wie mag er dit oplaadpunt gebruiken?", + "de": "Wer darf diese Ladestation benutzen?" }, "render": { "en": "Access is {access}", - "nl": "Toegang voor {access}" + "nl": "Toegang voor {access}", + "de": "Zugang ist {access}" }, "freeform": { "key": "access", @@ -148,7 +152,8 @@ "if": "access=yes", "then": { "en": "Anyone can use this charging station (payment might be needed)", - "nl": "Toegankelijk voor iedereen (mogelijks met aanmelden en/of te betalen)" + "nl": "Toegankelijk voor iedereen (mogelijks met aanmelden en/of te betalen)", + "de": "Jeder kann diese Ladestation nutzen (eventuell gegen Bezahlung)" } }, { @@ -160,7 +165,8 @@ }, "then": { "en": "Anyone can use this charging station (payment might be needed)", - "nl": "Toegankelijk voor iedereen (mogelijks met aanmelden en/of te betalen)" + "nl": "Toegankelijk voor iedereen (mogelijks met aanmelden en/of te betalen)", + "de": "Jeder kann diese Ladestation nutzen (eventuell gegen Bezahlung)" }, "hideInAnswer": true }, @@ -168,21 +174,24 @@ "if": "access=customers", "then": { "en": "Only customers of the place this station belongs to can use this charging station
E.g. a charging station operated by hotel which is only usable by their guests", - "nl": "Enkel klanten van de bijhorende plaats mogen dit oplaadpunt gebruiken
Bv. op de parking van een hotel en enkel toegankelijk voor klanten van dit hotel" + "nl": "Enkel klanten van de bijhorende plaats mogen dit oplaadpunt gebruiken
Bv. op de parking van een hotel en enkel toegankelijk voor klanten van dit hotel", + "de": "Nur Kunden des Ortes, zu dem diese Station gehört, können diese Ladestation nutzen
Z.B. eine von einem Hotel betriebene Ladestation, die nur von dessen Gästen genutzt werden kann" } }, { "if": "access=key", "then": { "en": "A key must be requested to access this charging station
E.g. a charging station operated by hotel which is only usable by their guests, which receive a key from the reception to unlock the charging station", - "nl": "Een sleutel is nodig om dit oplaadpunt te gebruiken
Bv. voor klanten van een hotel of een bar, die de sleutel aan de receptie kunnen krijgen" + "nl": "Een sleutel is nodig om dit oplaadpunt te gebruiken
Bv. voor klanten van een hotel of een bar, die de sleutel aan de receptie kunnen krijgen", + "de": "Für den Zugang zu dieser Ladestation muss ein Schlüssel angefordert werden
Z.B. eine von einem Hotel betriebene Ladestation, die nur von dessen Gästen genutzt werden kann, die an der Rezeption einen Schlüssel erhalten, um die Ladestation aufzuschließen" } }, { "if": "access=private", "then": { "en": "Not accessible to the general public (e.g. only accessible to the owners, employees, ...)", - "nl": "Niet toegankelijk voor het publiek
Bv. enkel toegankelijk voor de eigenaar, medewerkers ,..." + "nl": "Niet toegankelijk voor het publiek
Bv. enkel toegankelijk voor de eigenaar, medewerkers ,...", + "de": "Nicht für die Allgemeinheit zugänglich (z. B. nur für die Eigentümer, Mitarbeiter, ...)" } } ] @@ -196,7 +205,8 @@ }, "question": { "en": "How much vehicles can be charged here at the same time?", - "nl": "Hoeveel voertuigen kunnen hier opgeladen worden?" + "nl": "Hoeveel voertuigen kunnen hier opgeladen worden?", + "de": "Wie viele Fahrzeuge können hier gleichzeitig geladen werden?" }, "freeform": { "key": "capacity", @@ -217,7 +227,8 @@ "ifnot": "socket:schuko=", "then": { "en": "Schuko wall plug without ground pin (CEE7/4 type F)", - "nl": "Schuko stekker zonder aardingspin (CEE7/4 type F)" + "nl": "Schuko stekker zonder aardingspin (CEE7/4 type F)", + "de": "Schuko-Stecker ohne Erdungsstift (CEE7/4 Typ F)" }, "icon": { "path": "./assets/layers/charging_station/CEE7_4F.svg", @@ -245,7 +256,8 @@ }, "then": { "en": "Schuko wall plug without ground pin (CEE7/4 type F)", - "nl": "Schuko stekker zonder aardingspin (CEE7/4 type F)" + "nl": "Schuko stekker zonder aardingspin (CEE7/4 type F)", + "de": "Schuko-Stecker ohne Erdungsstift (CEE7/4 Typ F)" }, "hideInAnswer": true, "icon": { @@ -258,7 +270,8 @@ "ifnot": "socket:typee=", "then": { "en": "European wall plug with ground pin (CEE7/4 type E)", - "nl": "Europese stekker met aardingspin (CEE7/4 type E)" + "nl": "Europese stekker met aardingspin (CEE7/4 type E)", + "de": "Europäischer Netzstecker mit Erdungsstift (CEE7/4 Typ E)" }, "icon": { "path": "./assets/layers/charging_station/TypeE.svg", @@ -274,7 +287,8 @@ }, "then": { "en": "European wall plug with ground pin (CEE7/4 type E)", - "nl": "Europese stekker met aardingspin (CEE7/4 type E)" + "nl": "Europese stekker met aardingspin (CEE7/4 type E)", + "de": "Europäischer Netzstecker mit Erdungsstift (CEE7/4 Typ E)" }, "hideInAnswer": true, "icon": { @@ -287,7 +301,9 @@ "ifnot": "socket:chademo=", "then": { "en": "Chademo", - "nl": "Chademo" + "nl": "Chademo", + "ca": "Chademo", + "de": "Chademo" }, "icon": { "path": "./assets/layers/charging_station/Chademo_type4.svg", @@ -329,7 +345,9 @@ }, "then": { "en": "Chademo", - "nl": "Chademo" + "nl": "Chademo", + "ca": "Chademo", + "de": "Chademo" }, "hideInAnswer": true, "icon": { @@ -342,7 +360,8 @@ "ifnot": "socket:type1_cable=", "then": { "en": "Type 1 with cable (J1772)", - "nl": "Type 1 met kabel (J1772)" + "nl": "Type 1 met kabel (J1772)", + "de": "Typ 1 mit Kabel (J1772)" }, "icon": { "path": "./assets/layers/charging_station/Type1_J1772.svg", @@ -384,7 +403,8 @@ }, "then": { "en": "Type 1 with cable (J1772)", - "nl": "Type 1 met kabel (J1772)" + "nl": "Type 1 met kabel (J1772)", + "de": "Typ 1 mit Kabel (J1772)" }, "hideInAnswer": true, "icon": { @@ -397,7 +417,8 @@ "ifnot": "socket:type1=", "then": { "en": "Type 1 without cable (J1772)", - "nl": "Type 1 zonder kabel (J1772)" + "nl": "Type 1 zonder kabel (J1772)", + "de": "Typ 1 ohne Kabel (J1772)" }, "icon": { "path": "./assets/layers/charging_station/Type1_J1772.svg", @@ -439,7 +460,8 @@ }, "then": { "en": "Type 1 without cable (J1772)", - "nl": "Type 1 zonder kabel (J1772)" + "nl": "Type 1 zonder kabel (J1772)", + "de": " Typ 1 ohne Kabel (J1772)" }, "hideInAnswer": true, "icon": { @@ -452,7 +474,8 @@ "ifnot": "socket:type1_combo=", "then": { "en": "Type 1 CCS (aka Type 1 Combo)", - "nl": "Type 1 CCS (ook gekend als Type 1 Combo)" + "nl": "Type 1 CCS (ook gekend als Type 1 Combo)", + "de": "Typ 1 CCS (auch bekannt als Typ 1 Combo)" }, "icon": { "path": "./assets/layers/charging_station/Type1-ccs.svg", @@ -494,7 +517,8 @@ }, "then": { "en": "Type 1 CCS (aka Type 1 Combo)", - "nl": "Type 1 CCS (ook gekend als Type 1 Combo)" + "nl": "Type 1 CCS (ook gekend als Type 1 Combo)", + "de": " Typ 1 CCS (auch bekannt als Typ 1 Combo)" }, "hideInAnswer": true, "icon": { @@ -507,7 +531,8 @@ "ifnot": "socket:tesla_supercharger=", "then": { "en": "Tesla Supercharger", - "nl": "Tesla Supercharger" + "nl": "Tesla Supercharger", + "de": "Tesla Supercharger" }, "icon": { "path": "./assets/layers/charging_station/Tesla-hpwc-model-s.svg", @@ -549,7 +574,8 @@ }, "then": { "en": "Tesla Supercharger", - "nl": "Tesla Supercharger" + "nl": "Tesla Supercharger", + "de": "Tesla Supercharger" }, "hideInAnswer": true, "icon": { @@ -562,7 +588,8 @@ "ifnot": "socket:type2=", "then": { "en": "Type 2 (mennekes)", - "nl": "Type 2 (mennekes)" + "nl": "Type 2 (mennekes)", + "de": "Typ 2 (mennekes)" }, "icon": { "path": "./assets/layers/charging_station/Type2_socket.svg", @@ -604,7 +631,8 @@ }, "then": { "en": "Type 2 (mennekes)", - "nl": "Type 2 (mennekes)" + "nl": "Type 2 (mennekes)", + "de": "Typ 2 (mennekes)" }, "hideInAnswer": true, "icon": { @@ -617,7 +645,8 @@ "ifnot": "socket:type2_combo=", "then": { "en": "Type 2 CCS (mennekes)", - "nl": "Type 2 CCS (mennekes)" + "nl": "Type 2 CCS (mennekes)", + "de": "Typ 2 CCS (mennekes)" }, "icon": { "path": "./assets/layers/charging_station/Type2_CCS.svg", @@ -659,7 +688,8 @@ }, "then": { "en": "Type 2 CCS (mennekes)", - "nl": "Type 2 CCS (mennekes)" + "nl": "Type 2 CCS (mennekes)", + "de": "Typ 2 CCS (mennekes)" }, "hideInAnswer": true, "icon": { @@ -672,7 +702,8 @@ "ifnot": "socket:type2_cable=", "then": { "en": "Type 2 with cable (mennekes)", - "nl": "Type 2 met kabel (J1772)" + "nl": "Type 2 met kabel (J1772)", + "de": "Typ 2 mit Kabel (mennekes)" }, "icon": { "path": "./assets/layers/charging_station/Type2_tethered.svg", @@ -714,7 +745,8 @@ }, "then": { "en": "Type 2 with cable (mennekes)", - "nl": "Type 2 met kabel (J1772)" + "nl": "Type 2 met kabel (J1772)", + "de": "Typ 2 mit Kabel (mennekes)" }, "hideInAnswer": true, "icon": { @@ -727,7 +759,8 @@ "ifnot": "socket:tesla_supercharger_ccs=", "then": { "en": "Tesla Supercharger CCS (a branded type2_css)", - "nl": "Tesla Supercharger CCS (een type2 CCS met Tesla-logo)" + "nl": "Tesla Supercharger CCS (een type2 CCS met Tesla-logo)", + "de": "Tesla Supercharger CCS (ein Markenzeichen von type2_css)" }, "icon": { "path": "./assets/layers/charging_station/Type2_CCS.svg", @@ -769,7 +802,8 @@ }, "then": { "en": "Tesla Supercharger CCS (a branded type2_css)", - "nl": "Tesla Supercharger CCS (een type2 CCS met Tesla-logo)" + "nl": "Tesla Supercharger CCS (een type2 CCS met Tesla-logo)", + "de": "Tesla Supercharger CCS (ein Markenzeichen von type2_css)" }, "hideInAnswer": true, "icon": { @@ -782,7 +816,8 @@ "ifnot": "socket:tesla_destination=", "then": { "en": "Tesla Supercharger (destination)", - "nl": "Tesla Supercharger (destination)" + "nl": "Tesla Supercharger (destination)", + "de": "Tesla Supercharger (Destination)" }, "icon": { "path": "./assets/layers/charging_station/Tesla-hpwc-model-s.svg", @@ -830,7 +865,8 @@ }, "then": { "en": "Tesla Supercharger (destination)", - "nl": "Tesla Supercharger (destination)" + "nl": "Tesla Supercharger (destination)", + "de": "Tesla Supercharger (Destination)" }, "hideInAnswer": true, "icon": { @@ -843,7 +879,8 @@ "ifnot": "socket:tesla_destination=", "then": { "en": "Tesla supercharger (destination) (A Type 2 with cable branded as tesla)", - "nl": "Tesla supercharger (destination (Een Type 2 met kabel en Tesla-logo)" + "nl": "Tesla supercharger (destination (Een Type 2 met kabel en Tesla-logo)", + "de": "Tesla supercharger (Destination) (Typ 2 mit Kabel von Tesla)" }, "icon": { "path": "./assets/layers/charging_station/Type2_tethered.svg", @@ -891,7 +928,8 @@ }, "then": { "en": "Tesla supercharger (destination) (A Type 2 with cable branded as tesla)", - "nl": "Tesla supercharger (destination (Een Type 2 met kabel en Tesla-logo)" + "nl": "Tesla supercharger (destination (Een Type 2 met kabel en Tesla-logo)", + "de": "Tesla supercharger (Destination) (Typ 2 mit Kabel von Tesla)" }, "hideInAnswer": true, "icon": { @@ -904,7 +942,8 @@ "ifnot": "socket:USB-A=", "then": { "en": "USB to charge phones and small electronics", - "nl": "USB om GSMs en kleine electronica op te laden" + "nl": "USB om GSMs en kleine electronica op te laden", + "de": "USB zum Aufladen von Handys und kleinen Elektrogeräten" }, "icon": { "path": "./assets/layers/charging_station/usb_port.svg", @@ -920,7 +959,8 @@ }, "then": { "en": "USB to charge phones and small electronics", - "nl": "USB om GSMs en kleine electronica op te laden" + "nl": "USB om GSMs en kleine electronica op te laden", + "de": "USB zum Aufladen von Handys und kleinen Elektrogeräten" }, "hideInAnswer": true, "icon": { @@ -933,7 +973,8 @@ "ifnot": "socket:bosch_3pin=", "then": { "en": "Bosch Active Connect with 3 pins and cable", - "nl": "Bosch Active Connect met 3 pinnen aan een kabel" + "nl": "Bosch Active Connect met 3 pinnen aan een kabel", + "de": "Bosch Active Connect mit 3 Pins und Kabel" }, "icon": { "path": "./assets/layers/charging_station/bosch-3pin.svg", @@ -971,7 +1012,8 @@ }, "then": { "en": "Bosch Active Connect with 3 pins and cable", - "nl": "Bosch Active Connect met 3 pinnen aan een kabel" + "nl": "Bosch Active Connect met 3 pinnen aan een kabel", + "de": " Bosch Active Connect mit 3 Pins und Kabel" }, "hideInAnswer": true, "icon": { @@ -984,7 +1026,8 @@ "ifnot": "socket:bosch_5pin=", "then": { "en": "Bosch Active Connect with 5 pins and cable", - "nl": "Bosch Active Connect met 5 pinnen aan een kabel" + "nl": "Bosch Active Connect met 5 pinnen aan een kabel", + "de": "Bosch Active Connect mit 5 Pins und Kabel" }, "icon": { "path": "./assets/layers/charging_station/bosch-5pin.svg", @@ -1022,7 +1065,8 @@ }, "then": { "en": "Bosch Active Connect with 5 pins and cable", - "nl": "Bosch Active Connect met 5 pinnen aan een kabel" + "nl": "Bosch Active Connect met 5 pinnen aan een kabel", + "de": " Bosch Active Connect mit 5 Pins und Kabel" }, "hideInAnswer": true, "icon": { @@ -1036,11 +1080,13 @@ "id": "plugs-0", "question": { "en": "How much plugs of type
Schuko wall plug without ground pin (CEE7/4 type F)
are available here?", - "nl": "Hoeveel stekkers van type
Schuko stekker zonder aardingspin (CEE7/4 type F)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Schuko stekker zonder aardingspin (CEE7/4 type F)
heeft dit oplaadpunt?", + "de": "Wie viele Stecker vom Typ
Schuko-Stecker ohne Erdungsstift (CEE7/4 Typ F)
sind hier vorhanden?" }, "render": { "en": "There are {socket:schuko} plugs of type
Schuko wall plug without ground pin (CEE7/4 type F)
available here", - "nl": "Hier zijn {socket:schuko} stekkers van het type
Schuko stekker zonder aardingspin (CEE7/4 type F)
" + "nl": "Hier zijn {socket:schuko} stekkers van het type
Schuko stekker zonder aardingspin (CEE7/4 type F)
", + "de": "Hier sind {socket:schuko} Stecker des Typs
Schuko-Stecker ohne Erdungsstift (CEE7/4 Typ F)
vorhanden" }, "freeform": { "key": "socket:schuko", @@ -1057,11 +1103,13 @@ "id": "plugs-1", "question": { "en": "How much plugs of type
European wall plug with ground pin (CEE7/4 type E)
are available here?", - "nl": "Hoeveel stekkers van type
Europese stekker met aardingspin (CEE7/4 type E)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Europese stekker met aardingspin (CEE7/4 type E)
heeft dit oplaadpunt?", + "de": "Wie viele Stecker des Typs
Europäischer Wandstecker mit Erdungsstift (CEE7/4 Typ E)
sind hier vorhanden?" }, "render": { "en": "There are {socket:typee} plugs of type
European wall plug with ground pin (CEE7/4 type E)
available here", - "nl": "Hier zijn {socket:typee} stekkers van het type
Europese stekker met aardingspin (CEE7/4 type E)
" + "nl": "Hier zijn {socket:typee} stekkers van het type
Europese stekker met aardingspin (CEE7/4 type E)
", + "de": "Hier sind {socket:typee} Stecker des Typs
Europäischer Wandstecker mit Erdungsstift (CEE7/4 Typ E)
vorhanden" }, "freeform": { "key": "socket:typee", @@ -1078,7 +1126,7 @@ "id": "plugs-2", "question": { "en": "How much plugs of type
Chademo
are available here?", - "nl": "Hoeveel stekkers van type
Chademo
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Chademo
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:chademo} plugs of type
Chademo
available here", @@ -1099,7 +1147,7 @@ "id": "plugs-3", "question": { "en": "How much plugs of type
Type 1 with cable (J1772)
are available here?", - "nl": "Hoeveel stekkers van type
Type 1 met kabel (J1772)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Type 1 met kabel (J1772)
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:type1_cable} plugs of type
Type 1 with cable (J1772)
available here", @@ -1120,7 +1168,7 @@ "id": "plugs-4", "question": { "en": "How much plugs of type
Type 1 without cable (J1772)
are available here?", - "nl": "Hoeveel stekkers van type
Type 1 zonder kabel (J1772)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Type 1 zonder kabel (J1772)
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:type1} plugs of type
Type 1 without cable (J1772)
available here", @@ -1141,7 +1189,7 @@ "id": "plugs-5", "question": { "en": "How much plugs of type
Type 1 CCS (aka Type 1 Combo)
are available here?", - "nl": "Hoeveel stekkers van type
Type 1 CCS (ook gekend als Type 1 Combo)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Type 1 CCS (ook gekend als Type 1 Combo)
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:type1_combo} plugs of type
Type 1 CCS (aka Type 1 Combo)
available here", @@ -1162,7 +1210,7 @@ "id": "plugs-6", "question": { "en": "How much plugs of type
Tesla Supercharger
are available here?", - "nl": "Hoeveel stekkers van type
Tesla Supercharger
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Tesla Supercharger
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:tesla_supercharger} plugs of type
Tesla Supercharger
available here", @@ -1183,7 +1231,7 @@ "id": "plugs-7", "question": { "en": "How much plugs of type
Type 2 (mennekes)
are available here?", - "nl": "Hoeveel stekkers van type
Type 2 (mennekes)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Type 2 (mennekes)
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:type2} plugs of type
Type 2 (mennekes)
available here", @@ -1204,7 +1252,7 @@ "id": "plugs-8", "question": { "en": "How much plugs of type
Type 2 CCS (mennekes)
are available here?", - "nl": "Hoeveel stekkers van type
Type 2 CCS (mennekes)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Type 2 CCS (mennekes)
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:type2_combo} plugs of type
Type 2 CCS (mennekes)
available here", @@ -1225,7 +1273,7 @@ "id": "plugs-9", "question": { "en": "How much plugs of type
Type 2 with cable (mennekes)
are available here?", - "nl": "Hoeveel stekkers van type
Type 2 met kabel (J1772)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Type 2 met kabel (J1772)
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:type2_cable} plugs of type
Type 2 with cable (mennekes)
available here", @@ -1246,7 +1294,7 @@ "id": "plugs-10", "question": { "en": "How much plugs of type
Tesla Supercharger CCS (a branded type2_css)
are available here?", - "nl": "Hoeveel stekkers van type
Tesla Supercharger CCS (een type2 CCS met Tesla-logo)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Tesla Supercharger CCS (een type2 CCS met Tesla-logo)
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:tesla_supercharger_ccs} plugs of type
Tesla Supercharger CCS (a branded type2_css)
available here", @@ -1267,7 +1315,7 @@ "id": "plugs-11", "question": { "en": "How much plugs of type
Tesla Supercharger (destination)
are available here?", - "nl": "Hoeveel stekkers van type
Tesla Supercharger (destination)
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Tesla Supercharger (destination)
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:tesla_destination} plugs of type
Tesla Supercharger (destination)
available here", @@ -1309,7 +1357,7 @@ "id": "plugs-13", "question": { "en": "How much plugs of type
USB to charge phones and small electronics
are available here?", - "nl": "Hoeveel stekkers van type
USB om GSMs en kleine electronica op te laden
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
USB om GSMs en kleine electronica op te laden
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:USB-A} plugs of type
USB to charge phones and small electronics
available here", @@ -1330,7 +1378,7 @@ "id": "plugs-14", "question": { "en": "How much plugs of type
Bosch Active Connect with 3 pins and cable
are available here?", - "nl": "Hoeveel stekkers van type
Bosch Active Connect met 3 pinnen aan een kabel
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Bosch Active Connect met 3 pinnen aan een kabel
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:bosch_3pin} plugs of type
Bosch Active Connect with 3 pins and cable
available here", @@ -1351,7 +1399,7 @@ "id": "plugs-15", "question": { "en": "How much plugs of type
Bosch Active Connect with 5 pins and cable
are available here?", - "nl": "Hoeveel stekkers van type
Bosch Active Connect met 5 pinnen aan een kabel
heeft dit oplaadpunt?" + "nl": "Hoeveel stekkers van type
Bosch Active Connect met 5 pinnen aan een kabel
heeft dit oplaadpunt?" }, "render": { "en": "There are {socket:bosch_5pin} plugs of type
Bosch Active Connect with 5 pins and cable
available here", @@ -2945,7 +2993,8 @@ }, "render": { "en": "
Tesla supercharger (destination) (A Type 2 with cable branded as tesla)
outputs {socket:tesla_destination:voltage} volt", - "nl": "
Tesla supercharger (destination). (Een Type 2 met kabel en Tesla-logo)
heeft een spanning van {socket:tesla_destination:voltage} volt" + "nl": "
Tesla supercharger (destination). (Een Type 2 met kabel en Tesla-logo)
heeft een spanning van {socket:tesla_destination:voltage} volt", + "de": "
Tesla Supercharger (Destination) (Typ 2 mit Kabel von Tesla)
liefert {socket:tesla_destination:voltage} Volt" }, "freeform": { "key": "socket:tesla_destination:voltage", @@ -3079,11 +3128,13 @@ "group": "technical", "question": { "en": "What voltage do the plugs with
USB to charge phones and small electronics
offer?", - "nl": "Welke spanning levert de stekker van type
USB om GSMs en kleine electronica op te laden
" + "nl": "Welke spanning levert de stekker van type
USB om GSMs en kleine electronica op te laden
", + "de": "Welche Spannung liefern die Stecker mit
USB zum Laden von Handys und kleinen Elektrogeräten
?" }, "render": { "en": "
USB to charge phones and small electronics
outputs {socket:USB-A:voltage} volt", - "nl": "
USB om GSMs en kleine electronica op te laden
heeft een spanning van {socket:USB-A:voltage} volt" + "nl": "
USB om GSMs en kleine electronica op te laden
heeft een spanning van {socket:USB-A:voltage} volt", + "de": "
USB zum Aufladen von Telefonen und kleinen Elektrogeräten
liefert {socket:USB-A:voltage} Volt" }, "freeform": { "key": "socket:USB-A:voltage", @@ -3094,7 +3145,8 @@ "if": "socket:USB-A:voltage=5 V", "then": { "en": "USB to charge phones and small electronics outputs 5 volt", - "nl": "USB om GSMs en kleine electronica op te laden heeft een spanning van 5 volt" + "nl": "USB om GSMs en kleine electronica op te laden heeft een spanning van 5 volt", + "de": "USB zum Aufladen von Handys und kleinen Elektrogeräten liefert 5 Volt" }, "icon": { "path": "./assets/layers/charging_station/usb_port.svg", @@ -3206,7 +3258,8 @@ "group": "technical", "question": { "en": "What voltage do the plugs with
Bosch Active Connect with 3 pins and cable
offer?", - "nl": "Welke spanning levert de stekker van type
Bosch Active Connect met 3 pinnen aan een kabel
" + "nl": "Welke spanning levert de stekker van type
Bosch Active Connect met 3 pinnen aan een kabel
", + "de": "Welche Spannung bieten die Stecker mit
Bosch Active Connect mit 3 Pins und Kabel
?" }, "render": { "en": "
Bosch Active Connect with 3 pins and cable
outputs {socket:bosch_3pin:voltage} volt", @@ -3358,7 +3411,7 @@ "then": { "en": "24/7 opened (including holidays)", "nl": "24/7 open - ook tijdens vakanties", - "de": "durchgehend geöffnet (einschließlich Feiertage)", + "de": "Die Station ist durchgehend geöffnet (einschließlich Feiertage)", "es": "Abre 24/7 (incluidos días festivos)" } } @@ -3368,7 +3421,8 @@ "id": "fee", "question": { "en": "Does one have to pay to use this charging station?", - "nl": "Moet men betalen om dit oplaadpunt te gebruiken?" + "nl": "Moet men betalen om dit oplaadpunt te gebruiken?", + "de": "Muss man für die Nutzung dieser Ladestation bezahlen?" }, "mappings": [ { @@ -3382,7 +3436,8 @@ }, "then": { "nl": "Gratis te gebruiken (zonder aan te melden)", - "en": "Free to use (without authenticating)" + "en": "Free to use (without authenticating)", + "de": "Kostenlos nutzbar (ohne Authentifizierung)" } }, { @@ -3396,7 +3451,8 @@ }, "then": { "nl": "Gratis te gebruiken, maar aanmelden met een applicatie is verplicht", - "en": "Free to use, but one has to authenticate" + "en": "Free to use, but one has to authenticate", + "de": "Kostenlose Nutzung, aber man muss sich authentifizieren" } }, { @@ -3407,7 +3463,8 @@ }, "then": { "nl": "Gratis te gebruiken", - "en": "Free to use" + "en": "Free to use", + "de": "Kostenlose Nutzung" }, "hideInAnswer": true }, @@ -3420,7 +3477,8 @@ }, "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" + "en": "Paid use, but free for customers of the hotel/pub/hospital/... who operates the charging station", + "de": "Kostenpflichtige Nutzung, aber kostenlos für Kunden des Hotels / Pub / Krankenhauses / ... wer die Ladestation betreibt" } }, { @@ -3432,7 +3490,8 @@ }, "then": { "nl": "Betalend", - "en": "Paid use" + "en": "Paid use", + "de": "Nutzung gebührenpflichtig" } } ] @@ -3441,11 +3500,13 @@ "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?" + "nl": "Hoeveel moet men betalen om dit oplaadpunt te gebruiken?", + "de": "Wie viel muss man für die Nutzung dieser Ladestation bezahlen?" }, "render": { "en": "Using this charging station costs {charge}", - "nl": "Dit oplaadpunt gebruiken kost {charge}" + "nl": "Dit oplaadpunt gebruiken kost {charge}", + "de": "Die Nutzung dieser Ladestation kostet {charge}" }, "freeform": { "key": "charge" @@ -3573,11 +3634,13 @@ "id": "Auth phone", "render": { "en": "Authenticate by calling or SMS'ing to {authentication:phone_call:number}", - "nl": "Aanmelden door te bellen of te SMS'en naar {authentication:phone_call:number}" + "nl": "Aanmelden door te bellen of te SMS'en naar {authentication:phone_call:number}", + "de": "Authentifizierung durch Anruf oder SMS an {authentication:phone_call:number}" }, "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?" + "nl": "Wat is het telefoonnummer dat men moet bellen of SMS'en om zich aan te melden?", + "de": "Wie lautet die Telefonnummer für den Authentifizierungsanruf oder die SMS?" }, "freeform": { "key": "authentication:phone_call:number", @@ -3594,21 +3657,24 @@ "id": "maxstay", "question": { "en": "What is the maximum amount of time one is allowed to stay here?", - "nl": "Hoelang mag een voertuig hier blijven staan?" + "nl": "Hoelang mag een voertuig hier blijven staan?", + "de": "Wie lange darf man hier maximal parken?" }, "freeform": { "key": "maxstay" }, "render": { "en": "One can stay at most {canonical(maxstay)}", - "nl": "De maximale parkeertijd hier is {canonical(maxstay)}" + "nl": "De maximale parkeertijd hier is {canonical(maxstay)}", + "de": "Die maximale Parkdauer beträgt {canonical(maxstay)}" }, "mappings": [ { "if": "maxstay=unlimited", "then": { "en": "No timelimit on leaving your vehicle here", - "nl": "Geen maximum parkeertijd" + "nl": "Geen maximum parkeertijd", + "de": "Keine Höchstparkdauer" } } ], @@ -3734,11 +3800,13 @@ "id": "phone", "question": { "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?" + "nl": "Wat is het telefoonnummer van de beheerder van dit oplaadpunt?", + "de": "Welche Nummer kann man anrufen, wenn es ein Problem mit dieser Ladestation gibt?" }, "render": { "en": "In case of problems, call {phone}", - "nl": "Bij problemen, bel naar {phone}" + "nl": "Bij problemen, bel naar {phone}", + "de": "Bei Problemen, anrufen unter {phone}" }, "freeform": { "key": "phone", @@ -3749,11 +3817,13 @@ "id": "email", "question": { "en": "What is the email address of the operator?", - "nl": "Wat is het email-adres van de operator?" + "nl": "Wat is het email-adres van de operator?", + "de": "Wie lautet die E-Mail-Adresse des Betreibers?" }, "render": { "en": "In case of problems, send an email to {email}", - "nl": "Bij problemen, email naar {email}" + "nl": "Bij problemen, email naar {email}", + "de": "Bei Problemen senden Sie bitte eine E-Mail an {email}" }, "freeform": { "key": "email", @@ -4002,7 +4072,8 @@ ], "title": { "en": "a charging station for electrical bikes with a normal european wall plug (meant to charge electrical bikes)", - "nl": "een oplaadpunt voor elektrische fietsen met een gewoon Europees stopcontact (speciaal bedoeld voor fietsen)" + "nl": "een oplaadpunt voor elektrische fietsen met een gewoon Europees stopcontact (speciaal bedoeld voor fietsen)", + "de": "eine Ladestation für Elektrofahrräder mit einer normalen europäischen Steckdose (zum Laden von Elektrofahrrädern)" }, "preciseInput": { "preferredBackground": "map" @@ -4086,7 +4157,8 @@ "question": { "en": "All connectors", "nl": "Alle types", - "de": "Alle Anschlüsse" + "de": "Alle Anschlüsse", + "ca": "Tots els connectors" } }, { @@ -4229,12 +4301,14 @@ "human": { "en": " minutes", "nl": " minuten", - "ru": " минут" + "ru": " минут", + "ca": " minuts" }, "humanSingular": { "en": " minute", "nl": " minuut", - "ru": " минута" + "ru": " минута", + "ca": " minut" } }, { @@ -4251,12 +4325,14 @@ "human": { "en": " hours", "nl": " uren", - "ru": " часов" + "ru": " часов", + "ca": " hores" }, "humanSingular": { "en": " hour", "nl": " uur", - "ru": " час" + "ru": " час", + "ca": " hora" } }, { @@ -4270,12 +4346,14 @@ "human": { "en": " days", "nl": " day", - "ru": " дней" + "ru": " дней", + "ca": " dies" }, "humanSingular": { "en": " day", "nl": " dag", - "ru": " день" + "ru": " день", + "ca": " dia" } } ] @@ -4312,7 +4390,8 @@ "human": { "en": "Volts", "nl": "volt", - "ru": "Вольт" + "ru": "Вольт", + "ca": "Volts" } } ], @@ -4348,7 +4427,8 @@ ], "human": { "en": "A", - "nl": "A" + "nl": "A", + "ca": "A" } } ], @@ -4382,7 +4462,8 @@ "human": { "en": "kilowatt", "nl": "kilowatt", - "ru": "киловатт" + "ru": "киловатт", + "ca": "quilovats" } }, { @@ -4393,7 +4474,8 @@ "human": { "en": "megawatt", "nl": "megawatt", - "ru": "мегаватт" + "ru": "мегаватт", + "ca": "megavats" } } ], diff --git a/assets/layers/climbing/climbing.json b/assets/layers/climbing/climbing.json new file mode 100644 index 000000000..9c53a74a0 --- /dev/null +++ b/assets/layers/climbing/climbing.json @@ -0,0 +1,300 @@ +{ + "id": "climbing", + "name": { + "nl": "Klimgelegenheden", + "de": "Klettermöglichkeiten", + "en": "Climbing opportunities", + "ja": "登坂教室", + "fr": "Opportunité d’escalade", + "it": "Opportunità di arrampicata" + }, + "minzoom": 10, + "source": { + "osmTags": { + "and": [ + "sport=climbing", + "climbing!~route", + "leisure!~sports_centre", + "climbing!=route_top", + "climbing!=route_bottom" + ] + } + }, + "title": { + "render": { + "en": "Climbing opportunity", + "nl": "Klimgelegenheid", + "de": "Klettermöglichkeit", + "ja": "登坂教室", + "nb_NO": "Klatremulighet", + "fr": "Opportunité d’escalade", + "it": "Opportunità di arrampicata" + }, + "mappings": [ + { + "if": "climbing=crag", + "then": { + "en": "Climbing crag {name}", + "fr": "Mur d’escalade {name}", + "it": "Muro da arrampicata {name}", + "de": "Klettergarten {name}" + } + }, + { + "if": { + "and": [ + { + "or": [ + "climbing=area", + "climbing=site" + ] + }, + "name~*" + ] + }, + "then": { + "en": "Climbing area {name}", + "nl": "Klimsite {name}", + "fr": "Zone d’escalade {name}", + "de": "Klettergebiet {name}", + "it": "Area di arrampicata {name}" + } + }, + { + "if": { + "or": [ + "climbing=site", + "climbing=area" + ] + }, + "then": { + "en": "Climbing site", + "nl": "Klimsite", + "fr": "Site d’escalade", + "de": "Klettergebiet", + "it": "Sito di arrampicata", + "ca": "Llocs d'escalada" + } + }, + { + "if": "name~*", + "then": { + "nl": "Klimgelegenheid {name}", + "en": "Climbing opportunity {name}", + "fr": "Opportunité d’escalade {name}", + "de": "Klettermöglichkeit {name}", + "it": "Opportunità di arrampicata {name}" + } + } + ] + }, + "description": { + "nl": "Een klimgelegenheid", + "de": "Eine Klettergelegenheit", + "en": "A climbing opportunity", + "ja": "登坂教室", + "nb_NO": "En klatremulighet", + "fr": "Opportunité d’escalade", + "it": "Un’opportunità di arrampicata" + }, + "tagRenderings": [ + "images", + { + "id": "minimap", + "render": "{minimap(18, id, _contained_climbing_route_ids): height: 9rem; overflow: hidden; border-radius:3rem; }" + }, + { + "render": { + "en": "

Length overview

{histogram(_length_hist)}", + "fr": "

Résumé de longueur

{histogram(_length_hist)}", + "de": "

Längenübersicht

{histogram(_length_hist)}", + "it": "

Riassunto della lunghezza

{histogram(_length_hist)}" + }, + "condition": "_length_hist!~\\[\\]", + "id": "Contained routes length hist" + }, + { + "render": { + "en": "

Grades overview

{histogram(_difficulty_hist)}", + "fr": "

Résumé des difficultés

{histogram(_difficulty_hist)}", + "de": "

Schwierigkeitsübersicht

{histogram(_difficulty_hist)}", + "it": "

Riassunto delle difficoltà

{histogram(_difficulty_hist)}" + }, + "condition": "_difficulty_hist!~\\[\\]", + "id": "Contained routes hist" + }, + { + "render": { + "en": "

Contains {_contained_climbing_routes_count} routes

    {_contained_climbing_routes}
", + "fr": "

Contient {_contained_climbing_routes_count} voies

    {_contained_climbing_routes}
", + "it": "

Contiene {_contained_climbing_routes_count} vie

    {_contained_climbing_routes}
", + "de": "

Enthält {_contained_climbing_routes_count} Routen

    {_contained_climbing_routes}
" + }, + "condition": "_contained_climbing_routes~*", + "id": "Contained_climbing_routes" + }, + { + "render": { + "en": "{name}", + "nl": "{name}", + "de": "{name}", + "ca": "{name}", + "fr": "{name}", + "id": "{name}", + "ru": "{name}", + "ja": "{name}", + "it": "{name}" + }, + "question": { + "en": "What is the name of this climbing opportunity?", + "nl": "Wat is de naam van dit Klimgelegenheid?", + "de": "Wie heißt diese Klettergelegenheit?", + "ja": "この登坂教室の名前は何ですか?", + "fr": "Quel est le nom de ce site ?", + "it": "Qual è il nome di questa opportunità di arrampicata?" + }, + "freeform": { + "key": "name" + }, + "mappings": [ + { + "if": { + "and": [ + "noname=yes", + "name=" + ] + }, + "then": { + "en": "This climbing opportunity doesn't have a name", + "nl": "Dit Klimgelegenheid heeft geen naam", + "de": "Diese Klettergelegenheit hat keinen Namen", + "ja": "この登坂教室には名前がついていない", + "fr": "Ce site n’a pas de nom", + "it": "Questa opportunità di arrampicata non ha un nome" + } + } + ], + "id": "name" + }, + { + "question": "What kind of climbing opportunity is this?", + "mappings": [ + { + "if": "climbing=boulder", + "then": { + "en": "A climbing boulder - a single rock or cliff with one or a few climbing routes which can be climbed safely without rope", + "fr": "Rocher d’escalade, rocher avec une ou peu de voie permettant d’escalader sans corde", + "de": "Ein Kletterfelsen - ein einzelner Felsen oder eine Klippe mit einer oder wenigen Kletterrouten, die ohne Seil sicher bestiegen werden können", + "it": "Un masso per arrampicata (una singola roccia o falesia con una o poche vie di arrampicata che possono essere scalate in sicurezza senza una corda)" + } + }, + { + "if": "climbing=crag", + "then": { + "en": "A climbing crag - a single rock or cliff with at least a few climbing routes", + "fr": "Mur d’escalade, rocher avec plusieurs voies d’escalades", + "it": "Un muro da arrampicata (un singolo masso o falesia con almeno qualche via per arrampicata)", + "de": "Ein Kletterfelsen - ein einzelner Fels oder eine Klippe mit mindestens einigen Kletterrouten" + } + }, + { + "if": "climbing=area", + "then": "A climbing area with one or more climbing crags and/or boulders" + } + ], + "id": "Type" + }, + { + "question": { + "en": "What is the rock type here?", + "fr": "Quel est le type de roche ?", + "de": "Welchen Gesteinstyp gibt es hier?", + "it": "Qual è il tipo di roccia qua?" + }, + "render": { + "en": "The rock type is {rock}", + "fr": "La roche est du {rock}", + "de": "Der Gesteinstyp ist {rock}", + "it": "Il tipo di roccia è {rock}" + }, + "freeform": { + "key": "rock" + }, + "mappings": [ + { + "if": "rock=limestone", + "then": { + "en": "Limestone", + "nl": "Kalksteen", + "fr": "Calcaire", + "de": "Kalkstein", + "it": "Calcare" + } + } + ], + "condition": { + "or": [ + "climbing=crag", + "natural=cliff", + "natural=bare_rock" + ] + }, + "id": "Rock type (crag/rock/cliff only)" + } + ], + "presets": [ + { + "tags": [ + "sport=climbing" + ], + "title": { + "en": "a climbing opportunity", + "nl": "een klimgelegenheid", + "de": "eine klettermöglichkeit", + "ja": "登坂教室", + "nb_NO": "en klatremulighet", + "fr": "une opportunité d’escalade", + "it": "una opportunità di arrampicata" + }, + "description": { + "nl": "Een klimgelegenheid", + "de": "Eine Klettergelegenheit", + "en": "A climbing opportunity", + "ja": "登坂教室", + "nb_NO": "En klatremulighet", + "fr": "Opportunité d’escalade", + "it": "Un’opportunità di arrampicata" + } + } + ], + "calculatedTags": [ + "_contained_climbing_routes_properties=feat.overlapWith('climbing_route').map(f => f.feat.properties).map(p => {return {id: p.id, name: p.name, 'climbing:grade:french': p['climbing:grade:french'], 'climbing:length': p['climbing:length']} })", + "_contained_climbing_routes=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => `
  • ${p.name ?? 'climbing route'} (${p['climbing:grade:french'] ?? 'unknown difficulty'}, ${p['climbing:length'] ?? 'unkown length'} meter)
  • `).join('')", + "_contained_climbing_route_ids=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p.id)", + "_difficulty_hist=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p['climbing:grade:french'])", + "_length_hist=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p['climbing:length'])", + "_contained_climbing_routes_count=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').length" + ], + "mapRendering": [ + { + "icon": { + "render": "./assets/themes/climbing/climbing_no_rope.svg" + }, + "iconSize": { + "render": "40,40,center" + }, + "location": [ + "point", + "centroid" + ] + }, + { + "color": { + "render": "#d38d5fAA" + }, + "width": { + "render": "8" + } + } + ] +} \ No newline at end of file diff --git a/assets/layers/climbing_club/climbing_club.json b/assets/layers/climbing_club/climbing_club.json new file mode 100644 index 000000000..6720a1753 --- /dev/null +++ b/assets/layers/climbing_club/climbing_club.json @@ -0,0 +1,189 @@ +{ + "id": "climbing_club", + "name": { + "de": "Klettervereine", + "nl": "Klimclub", + "en": "Climbing club", + "ru": "Клуб скалолазания", + "ja": "クライミングクラブ", + "zh_Hant": "攀岩社團", + "nb_NO": "Klatreklubb", + "fr": "Club d’escalade", + "it": "Club di arrampicata", + "hu": "Mászóegyesület" + }, + "minzoom": 10, + "source": { + "osmTags": { + "or": [ + "club=climbing", + { + "and": [ + "sport=climbing", + { + "or": [ + "office~*", + "club~*" + ] + } + ] + } + ] + } + }, + "title": { + "render": { + "en": "Climbing club", + "nl": "Klimclub", + "de": "Kletterverein", + "ru": "Клуб скалолазания", + "ja": "クライミングクラブ", + "zh_Hant": "攀岩社團", + "nb_NO": "Klatreklubb", + "fr": "Club d’escalade", + "it": "Club di arrampicata" + }, + "mappings": [ + { + "if": "office~*", + "then": { + "nl": "Klimorganisatie", + "en": "Climbing NGO", + "de": "Kletter-Organisation", + "ja": "クライミングNGO", + "zh_Hant": "攀岩 NGO", + "fr": "Association d’escalade", + "it": "Associazione di arrampicata", + "hu": "Mászószervezet" + } + } + ] + }, + "description": { + "de": "Ein Kletterverein oder -organisation", + "nl": "Een klimclub of organisatie", + "en": "A climbing club or organisation", + "ja": "クライミングクラブや団体", + "zh_Hant": "攀岩社團或組織", + "nb_NO": "En klatreklubb eller organisasjoner", + "fr": "Club ou association d’escalade", + "it": "Un club o associazione di arrampacata", + "hu": "Mászóegyesület vagy -szervezet" + }, + "tagRenderings": [ + { + "render": { + "en": "{name}", + "nl": "{name}", + "de": "{name}", + "ca": "{name}", + "fr": "{name}", + "id": "{name}", + "ru": "{name}", + "ja": "{name}", + "zh_Hant": "{name}", + "it": "{name}", + "hu": "{name}" + }, + "question": { + "en": "What is the name of this climbing club or NGO?", + "de": "Wie lautet der Name dieses Vereins oder Organisation?", + "nl": "Wat is de naam van deze klimclub?", + "ja": "この登山クラブやNGOの名前は何ですか?", + "fr": "Quel est le nom du club ou de l’association ?", + "it": "Qual è il nome di questo club o associazione di arrampicata?", + "hu": "Mi a neve ennek a mászóegyesületnek vagy szervezetnek?" + }, + "freeform": { + "key": "name" + }, + "id": "climbing_club-name" + }, + "website", + "email", + "phone", + "opening_hours" + ], + "presets": [ + { + "tags": [ + "club=sport", + "sport=climbing" + ], + "title": { + "de": "eine kletterverein", + "en": "a climbing club", + "nl": "een klimclub", + "ja": "クライミングクラブ", + "nb_NO": "en klatreklubb", + "ru": "Клуб скалолазания", + "fr": "une club d’escalade", + "it": "una club di arrampicata", + "hu": "Mászóegyesület" + }, + "description": { + "de": "Ein Kletterverein", + "nl": "Een klimclub", + "en": "A climbing club", + "ja": "クライミングクラブ", + "nb_NO": "En klatreklubb", + "ru": "Клуб скалолазания", + "fr": "Un club d’escalade", + "it": "Un club di arrampicata", + "hu": "Egy mászóegyesület" + } + }, + { + "tags": [ + "office=ngo", + "sport=climbing" + ], + "title": { + "de": "Eine Kletterorganisation", + "en": "a climbing ngo", + "nl": "een een klimorganisatie", + "ja": "クライミングNGO", + "fr": "une association d’escalade", + "it": "una associazione di arrampicata", + "hu": "Mászószervezet" + }, + "description": { + "de": "Eine Organisation, die sich mit dem Klettern beschäftigt", + "nl": "Een VZW die werkt rond klimmen", + "en": "An NGO working around climbing", + "ja": "登山に関わるNGO", + "fr": "Une association d’escalade", + "it": "Un’associazione che ha a che fare con l’arrampicata", + "hu": "Mászással foglalkozó civil szervezet" + } + } + ], + "mapRendering": [ + { + "icon": { + "render": "./assets/themes/climbing/club.svg" + }, + "iconBadges": [ + { + "if": "opening_hours~*", + "then": "isOpen" + } + ], + "iconSize": { + "render": "40,40,center" + }, + "location": [ + "point", + "centroid" + ], + "label": { + "mappings": [ + { + "if": "name~*", + "then": "
    {name}
    " + } + ] + } + } + ] +} \ No newline at end of file diff --git a/assets/layers/climbing_gym/climbing_gym.json b/assets/layers/climbing_gym/climbing_gym.json new file mode 100644 index 000000000..d93037ae6 --- /dev/null +++ b/assets/layers/climbing_gym/climbing_gym.json @@ -0,0 +1,114 @@ +{ + "id": "climbing_gym", + "name": { + "de": "Kletterhallen", + "en": "Climbing gyms", + "nl": "Klimzalen", + "ja": "クライミングジム", + "fr": "Salle d’escalade", + "it": "Palestre di arrampicata", + "ru": "Комплексы скалолазания" + }, + "minzoom": 10, + "source": { + "osmTags": { + "and": [ + "sport=climbing", + "leisure=sports_centre" + ] + } + }, + "title": { + "render": { + "nl": "Klimzaal", + "de": "Kletterhalle", + "en": "Climbing gym", + "ja": "クライミングジム", + "fr": "Salle d’escalade", + "it": "Palestra di arrampicata", + "ru": "Комплекс скалолазания" + }, + "mappings": [ + { + "if": "name~*", + "then": { + "nl": "Klimzaal {name}", + "de": "Kletterhalle {name}", + "en": "Climbing gym {name}", + "ja": "クライミングジム{name}", + "fr": "Salle d’escalade {name}", + "it": "Palestra di arrampicata {name}" + } + } + ] + }, + "description": { + "de": "Eine Kletterhalle", + "en": "A climbing gym", + "ja": "クライミングジム", + "nl": "Een klimzaal", + "fr": "Une salle d’escalade", + "it": "Una palestra di arrampicata", + "ru": "Комплекс скалолазания" + }, + "tagRenderings": [ + "images", + { + "render": { + "en": "{name}", + "nl": "{name}", + "de": "{name}", + "ca": "{name}", + "fr": "{name}", + "id": "{name}", + "ru": "{name}", + "ja": "{name}", + "it": "{name}" + }, + "question": { + "en": "What is the name of this climbing gym?", + "nl": "Wat is de naam van dit Klimzaal?", + "de": "Wie heißt diese Kletterhalle?", + "ja": "このクライミングジムは何という名前ですか?", + "fr": "Quel est le nom de la salle d’escalade ?", + "it": "Qual è il nome di questa palestra di arrampicata?" + }, + "freeform": { + "key": "name" + }, + "id": "name" + }, + "website", + "phone", + "email", + "opening_hours" + ], + "mapRendering": [ + { + "icon": { + "render": "./assets/themes/climbing/climbing_gym.svg" + }, + "iconBadges": [ + { + "if": "opening_hours~*", + "then": "isOpen" + } + ], + "iconSize": { + "render": "40,40,center" + }, + "location": [ + "point", + "centroid" + ], + "label": { + "mappings": [ + { + "if": "name~*", + "then": "
    {name}
    " + } + ] + } + } + ] +} \ No newline at end of file diff --git a/assets/layers/climbing_opportunity/climbing_opportunity.json b/assets/layers/climbing_opportunity/climbing_opportunity.json new file mode 100644 index 000000000..c9afa69f0 --- /dev/null +++ b/assets/layers/climbing_opportunity/climbing_opportunity.json @@ -0,0 +1,142 @@ +{ + "id": "climbing_opportunity", + "name": { + "nl": "Klimgelegenheiden?", + "de": "Klettermöglichkeiten?", + "en": "Climbing opportunities?", + "ja": "登坂教室?", + "nb_NO": "Klatremuligheter?", + "fr": "Opportunités d’escalade ?", + "it": "Opportunità di arrampicata?" + }, + "minzoom": 19, + "source": { + "osmTags": { + "and": [ + { + "or": [ + "leisure=sports_centre", + "barrier=wall", + "barrier=retaining_wall", + "natural=cliff", + "natural=rock", + "natural=stone" + ] + }, + "climbing=" + ] + } + }, + "title": { + "render": { + "en": "Climbing opportunity?", + "nl": "Klimgelegenheid?", + "de": "Klettermöglichkeit?", + "ja": "登坂教室?", + "nb_NO": "Klatremulighet?", + "fr": "Opportunité d’escalade ?", + "it": "Opportunità di arrampicata?" + } + }, + "description": { + "nl": "Een klimgelegenheid?", + "de": "Eine Klettergelegenheit?", + "en": "A climbing opportunity?", + "ja": "登坂教室?", + "nb_NO": "En klatremulighet?", + "fr": "Opportunité d’escalade ?", + "it": "Un’opportunità di arrampicata?" + }, + "tagRenderings": [ + { + "id": "climbing-opportunity-name", + "render": { + "en": "{name}", + "de": "{name}", + "ca": "{name}", + "fr": "{name}", + "id": "{name}", + "ru": "{name}", + "ja": "{name}", + "nl": "{name}", + "it": "{name}" + }, + "condition": "name~*" + }, + { + "id": "climbing-possible", + "question": { + "en": "Is climbing possible here?", + "de": "Kann hier geklettert werden?", + "ja": "ここで登坂はできますか?", + "nb_NO": "Er klatring mulig her?", + "fr": "Est-il possible d’escalader ici ?", + "it": "È possibile arrampicarsi qua?" + }, + "mappings": [ + { + "if": { + "and": [ + "sport=climbing" + ] + }, + "then": { + "en": "Climbing is possible here", + "de": "Hier kann geklettert werden", + "ja": "ここでは登ることができる", + "nb_NO": "Klatring er mulig her", + "nl": "Klimmen is hier niet toegelaten", + "fr": "Escalader est possible", + "it": "È possibile arrampicarsi qua" + } + }, + { + "if": "climbing=no", + "then": { + "en": "Climbing is not possible here", + "de": "Hier kann nicht geklettert werden", + "ja": "ここでは登ることができない", + "nb_NO": "Klatring er ikke mulig her", + "nl": "Klimmen is hier niet toegelaten", + "fr": "Escalader n’est pas possible", + "it": "Non è possibile arrampicarsi qua" + } + }, + { + "if": { + "and": [ + "sport!~climbing" + ] + }, + "then": { + "en": "Climbing is not possible here", + "de": "Hier kann nicht geklettert werden", + "ja": "ここでは登ることができない", + "nb_NO": "Klatring er ikke mulig her", + "nl": "Klimmen is hier niet mogelijk", + "fr": "Escalader n’est pas possible", + "it": "Non è possibile arrampicarsi qua" + }, + "hideInAnswer": true + } + ] + } + ], + "mapRendering": [ + { + "icon": "./assets/themes/climbing/climbing_unknown.svg", + "location": [ + "point", + "centroid" + ] + }, + { + "color": { + "render": "#ddff55AA" + }, + "width": { + "render": "2" + } + } + ] +} \ No newline at end of file diff --git a/assets/layers/climbing_route/climbing_route.json b/assets/layers/climbing_route/climbing_route.json new file mode 100644 index 000000000..faba96032 --- /dev/null +++ b/assets/layers/climbing_route/climbing_route.json @@ -0,0 +1,246 @@ +{ + "id": "climbing_route", + "name": { + "en": "Climbing routes", + "de": "Kletterrouten", + "nl": "Klimroute", + "ja": "登坂ルート", + "nb_NO": "Klatreruter", + "fr": "Voies d’escalade", + "it": "Vie di arrampicata" + }, + "minzoom": 18, + "source": { + "osmTags": { + "and": [ + "climbing=route" + ] + } + }, + "title": { + "render": { + "de": "Kleterroute", + "en": "Climbing route", + "nl": "Klimroute", + "ja": "登坂ルート", + "nb_NO": "Klatrerute", + "it": "Via di arrampicata", + "fr": "Voie d’escalade" + }, + "mappings": [ + { + "if": "name~*", + "then": { + "de": "Kleterroute {name}", + "en": "Climbing route {name}", + "nl": "Klimroute {name}", + "ja": "登坂ルート{name}", + "it": "Via di arrampicata {name}", + "fr": "Voie d’escalade {name}" + } + } + ] + }, + "tagRenderings": [ + "images", + { + "render": { + "en": "{name}", + "nl": "{name}", + "de": "{name}", + "ca": "{name}", + "fr": "{name}", + "id": "{name}", + "ru": "{name}", + "ja": "{name}", + "it": "{name}", + "nb_NO": "{name}" + }, + "question": { + "en": "What is the name of this climbing route?", + "de": "Wie heißt diese Kletterroute?", + "nl": "Hoe heet deze klimroute?", + "ja": "この登坂ルートの名前は何ですか?", + "it": "Come si chiama questa via di arrampicata?", + "fr": "Quel est le nom de cette voie d’escalade ?", + "nb_NO": "Hva er navnet på denne klatreruten?" + }, + "freeform": { + "key": "name" + }, + "mappings": [ + { + "if": { + "and": [ + "noname=yes", + "name=" + ] + }, + "then": { + "en": "This climbing route doesn't have a name", + "de": "Diese Kletterroute hat keinen Namen", + "nl": "Deze klimroute heeft geen naam", + "ja": "この登坂ルートには名前がありません", + "it": "Questa via di arrampicata non ha un nome", + "fr": "Cette voie n’a pas de nom", + "nb_NO": "Denne klatreruten har ikke noe navn" + } + } + ], + "id": "Name" + }, + { + "question": { + "en": "How long is this climbing route (in meters)?", + "nl": "Hoe lang is deze klimroute (in meters)?", + "it": "Quanto è lunga questa via di arrampicata (in metri)?", + "fr": "Quelle est la longueur de cette voie (en mètres) ?", + "de": "Wie lang ist diese Kletterroute (in Metern)?", + "nb_NO": "Hvor mange meter er klatreruten?" + }, + "render": { + "de": "Diese Route ist {canonical(climbing:length)} lang", + "en": "This route is {canonical(climbing:length)} long", + "nl": "Deze klimroute is {canonical(climbing:length)} lang", + "ja": "このルート長は、 {canonical(climbing:length)} メーターです", + "nb_NO": "Denne ruten er {canonical(climbing:length)} lang", + "it": "Questo percorso è lungo {canonical(climbing:length)}", + "fr": "Cette voie fait {canonical(climbing:length)} de long" + }, + "freeform": { + "key": "climbing:length", + "type": "pnat" + }, + "id": "Length" + }, + { + "question": { + "en": "What is the grade of this climbing route according to the french/belgian system?", + "nl": "Hoe moeilijk is deze klimroute volgens het Franse/Belgische systeem?", + "it": "Qual è la difficoltà di questa via di arrampicata nel sistema francese/belga?", + "fr": "Quelle est la difficulté de cette voie selon le système franco-belge ?", + "de": "Wie hoch ist der Schwierigkeitsgrad dieser Kletterroute nach dem französisch/belgischen System?" + }, + "render": { + "de": "Die Schwierigkeit ist {climbing:grade:french} entsprechend des französisch/belgischen Systems", + "en": "The grade is {climbing:grade:french} according to the french/belgian system", + "nl": "De klimmoeilijkheid is {climbing:grade:french} volgens het Franse/Belgische systeem", + "ja": "フランス/ベルギーのランク評価システムによると、{climbing:grade:french}の困難度です", + "it": "Il grado di difficoltà è {climbing:grade:french} nel sistema francese/belga", + "fr": "Selon le système franco-belge, la difficulté de cette voie est de {climbing:grade:french}" + }, + "freeform": { + "key": "climbing:grade:french" + }, + "id": "Difficulty" + }, + { + "question": { + "en": "How many bolts does this route have before reaching the anchor?", + "fr": "Combien de prises cette voie possède avant d’atteindre la moulinette ?", + "de": "Wie viele Haken gibt es auf dieser Kletterroute bevor der Umlenker bzw. Standhaken erreicht ist?", + "it": "Quanti bulloni sono presenti in questo percorso prima di arrivare alla moulinette?" + }, + "render": { + "en": "This route has {climbing:bolts} bolts", + "fr": "Cette voie a {climbing:bolts} prises", + "de": "Diese Kletterroute hat {climbing:bolts} Haken", + "it": "Questo percorso ha {climbing:bolts} bulloni" + }, + "freeform": { + "key": "climbing:bolts", + "type": "pnat", + "addExtraTag": [ + "climbing:bolted=yes" + ] + }, + "mappings": [ + { + "if": "climbing:bolted=no", + "then": { + "en": "This route is not bolted", + "fr": "Cette voie n’a pas de prises", + "de": "Auf dieser Kletterroute sind keine Haken vorhanden", + "it": "In questo percorso non sono presenti bulloni" + }, + "hideInAnswer": true + }, + { + "if": "climbing:bolted=no&climbing:bolts=", + "then": { + "en": "This route is not bolted", + "fr": "Cette voie n’a pas de prises", + "de": "Auf dieser Kletterroute sind keine Haken vorhanden", + "it": "In questo percorso non sono presenti bulloni" + } + } + ], + "id": "Bolts" + }, + { + "question": "Is there other relevant info?", + "render": "

    Description


    {description}", + "freeform": { + "key": "description" + }, + "id": "Description" + }, + { + "render": { + "en": "The rock type is {_embedding_features_with_rock:rock} as stated on the surrounding crag", + "fr": "Le type de roche est {_embedding_features_with_rock:rock} selon le mur", + "it": "Il tipo di roccia è {_embedding_features_with_rock:rock} come dichiarato sul muro circostante", + "de": "Der Gesteinstyp ist {_embedding_features_with_rock:rock}, wie auf dem umgebenden Felsen angegeben" + }, + "freeform": { + "key": "_embedding_features_with_rock:rock" + }, + "id": "Rock type" + } + ], + "presets": [ + { + "title": { + "en": "a climbing route", + "nl": "een klimroute", + "fr": "une voie d’escalade", + "de": "eine kletterroute", + "it": "una via di arrampicata" + }, + "tags": [ + "sport=climbing", + "climbing=route" + ] + } + ], + "mapRendering": [ + { + "icon": { + "render": "circle:white;./assets/themes/climbing/climbing_route.svg" + }, + "iconSize": { + "render": "28,28,center" + }, + "location": [ + "point", + "centroid" + ], + "label": { + "mappings": [ + { + "if": "name~*", + "then": "
    {name}
    " + } + ] + } + }, + { + "color": { + "render": "#0f0" + }, + "width": { + "render": "4" + } + } + ] +} \ No newline at end of file diff --git a/assets/layers/crossings/crossings.json b/assets/layers/crossings/crossings.json index 410c82f83..95a14e434 100644 --- a/assets/layers/crossings/crossings.json +++ b/assets/layers/crossings/crossings.json @@ -4,7 +4,8 @@ "en": "Crossings", "nl": "Oversteekplaatsen", "de": "Kreuzungen", - "fr": "Traversée" + "fr": "Traversée", + "ca": "Encreuaments" }, "description": { "en": "Crossings for pedestrians and cyclists", @@ -26,7 +27,8 @@ "en": "Crossing", "nl": "Oversteekplaats", "de": "Kreuzung", - "fr": "Traversée" + "fr": "Traversée", + "ca": "Encreuament" }, "mappings": [ { @@ -36,7 +38,8 @@ "nl": "Verkeerslicht", "ru": "Светофор", "de": "Ampel", - "fr": "Feu de signalisation" + "fr": "Feu de signalisation", + "ca": "Semàfor" } }, { @@ -56,7 +59,8 @@ "en": "a crossing", "nl": "een oversteekplaats", "de": "eine kreuzung", - "fr": "une traversée" + "fr": "une traversée", + "ca": "un pas de vianants" }, "tags": [ "highway=crossing" @@ -132,7 +136,8 @@ "then": { "en": "Zebra crossing", "nl": "Zebrapad", - "de": "Zebrastreifen" + "de": "Zebrastreifen", + "ca": "Pas de zebra" }, "hideInAnswer": true }, diff --git a/assets/layers/cycleways_and_roads/cycleways_and_roads.json b/assets/layers/cycleways_and_roads/cycleways_and_roads.json index 7a1101b2e..3e73e32b3 100644 --- a/assets/layers/cycleways_and_roads/cycleways_and_roads.json +++ b/assets/layers/cycleways_and_roads/cycleways_and_roads.json @@ -35,7 +35,8 @@ "nl": "Fietspaden", "de": "Radwege", "ru": "Велосипедные дорожки", - "fr": "Pistes cyclables" + "fr": "Pistes cyclables", + "ca": "Vies ciclistes" }, "mappings": [ { @@ -50,7 +51,8 @@ "en": "Cycleway", "de": "Radweg", "ru": "Велосипедная дорожка", - "fr": "Piste cyclable" + "fr": "Piste cyclable", + "ca": "Via ciclista" } }, { @@ -59,7 +61,8 @@ "nl": "Fietssuggestiestrook", "en": "Shared lane", "de": "Gemeinsame Fahrspur", - "fr": "Voie partagée" + "fr": "Voie partagée", + "ca": "Carril compartit" } }, { @@ -68,7 +71,8 @@ "nl": "Fietsstrook", "en": "Bike lane", "de": "Fahrradspur", - "fr": "Bande cyclable" + "fr": "Bande cyclable", + "ca": "Carril bici" } }, { @@ -86,7 +90,8 @@ "nl": "Fietsstraat", "en": "Cyclestreet", "de": "Fahrradstraße", - "fr": "Vélorue" + "fr": "Vélorue", + "ca": "Carrer ciclista" } } ] @@ -817,7 +822,8 @@ "en": "Compulsory cycleway", "nl": "Verplicht fietspad", "de": "Vorgeschriebener Radweg", - "id": "Jalur sepeda wajib" + "id": "Jalur sepeda wajib", + "ca": "Via ciclista obligatòria" }, "hideInAnswer": "_country!=be", "icon": { @@ -845,7 +851,8 @@ "en": "Segregated foot/cycleway", "nl": "Afgescheiden voet-/fietspad", "de": "Getrennter Fuß-/Radweg", - "id": "Jalur pejalan kaki/sepeda terpisah" + "id": "Jalur pejalan kaki/sepeda terpisah", + "ca": "Via segregada a peu/ciclista" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -863,7 +870,8 @@ "en": "Unsegregated foot/cycleway", "nl": "Gedeeld voet-/fietspad", "de": "Gemeinsamer Fuß-/Radweg", - "id": "Jalur pejalan kaki/sepeda tidak terpisah" + "id": "Jalur pejalan kaki/sepeda tidak terpisah", + "ca": "Via no segregada a peu/ciclista" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -916,7 +924,8 @@ "en": "Compulsory cycleway", "nl": "Verplicht fietspad", "de": "Vorgeschriebener Radweg", - "id": "Jalur sepeda wajib" + "id": "Jalur sepeda wajib", + "ca": "Via ciclista obligatòria" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -948,7 +957,8 @@ "then": { "en": "Segregated foot/cycleway", "nl": "Afgescheiden voet-/fietspad", - "de": "Getrennter Fuß-/Radweg" + "de": "Getrennter Fuß-/Radweg", + "ca": "Via segregada a peu/ciclista" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -969,7 +979,8 @@ "then": { "en": "Unsegregated foot/cycleway", "nl": "Gedeeld voet-/fietspad", - "de": "Gemeinsamer Fuß-/Radweg" + "de": "Gemeinsamer Fuß-/Radweg", + "ca": "Via no segregada a peu/ciclista" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -989,7 +1000,8 @@ "if": "traffic_sign=NL:G11", "then": { "en": "Compulsory cycleway", - "nl": "Verplicht fietspad" + "nl": "Verplicht fietspad", + "ca": "Via ciclista obligatòria" }, "hideInAnswer": "_country!=nl", "addExtraTags": [ diff --git a/assets/layers/defibrillator/defibrillator.json b/assets/layers/defibrillator/defibrillator.json index e388be166..f7c65863d 100644 --- a/assets/layers/defibrillator/defibrillator.json +++ b/assets/layers/defibrillator/defibrillator.json @@ -477,7 +477,8 @@ "it": "{opening_hours_table(opening_hours)}", "ru": "{opening_hours_table(opening_hours)}", "de": "{opening_hours_table(opening_hours)}", - "sl": "{opening_hours_table(opening_hours)}" + "sl": "{opening_hours_table(opening_hours)}", + "ca": "{opening_hours_table(opening_hours)}" }, "question": { "en": "At what times is this defibrillator available?", @@ -563,7 +564,8 @@ "it": "Verificato oggi!", "ru": "Проверено сегодня!", "de": "Heute überprüft!", - "sl": "Preverjeno danes!" + "sl": "Preverjeno danes!", + "ca": "Comprovat avui!" } } ], diff --git a/assets/layers/direction/direction.json b/assets/layers/direction/direction.json index 5e2b3c5e0..bd98af2f7 100644 --- a/assets/layers/direction/direction.json +++ b/assets/layers/direction/direction.json @@ -6,7 +6,8 @@ "fr": "Visualisation de la direction", "it": "Visualizzazione della direzione", "ru": "Визуализация направления", - "de": "Aufnahmewinkel der Kamera anzeigen" + "de": "Aufnahmewinkel der Kamera anzeigen", + "ca": "Direcció de la visualització" }, "minzoom": 16, "source": { diff --git a/assets/layers/drinking_water/drinking_water.json b/assets/layers/drinking_water/drinking_water.json index 9223d0a38..a902b9c30 100644 --- a/assets/layers/drinking_water/drinking_water.json +++ b/assets/layers/drinking_water/drinking_water.json @@ -9,7 +9,8 @@ "it": "Acqua potabile", "ru": "Питьевая вода", "id": "Air minum", - "hu": "Ivóvíz" + "hu": "Ivóvíz", + "ca": "Aigua potable" }, "title": { "render": { @@ -21,7 +22,8 @@ "it": "Acqua potabile", "ru": "Питьевая вода", "id": "Air minum", - "hu": "Ivóvíz" + "hu": "Ivóvíz", + "ca": "Aigua potable" } }, "source": { diff --git a/assets/layers/entrance/entrance.json b/assets/layers/entrance/entrance.json index a894b20ac..09d4b178a 100644 --- a/assets/layers/entrance/entrance.json +++ b/assets/layers/entrance/entrance.json @@ -3,7 +3,8 @@ "name": { "en": "Entrance", "nl": "Toegang", - "de": "Eingänge" + "de": "Eingänge", + "ca": "Entrada" }, "description": { "en": "A layer showing entrances and offering capabilities to survey some advanced data which is important for e.g. wheelchair users (but also bicycle users, people who want to deliver, ...)", @@ -21,7 +22,8 @@ "title": { "render": { "en": "Entrance", - "nl": "Ingang" + "nl": "Ingang", + "ca": "Entrada" } }, "tagRenderings": [ diff --git a/assets/layers/etymology/etymology.json b/assets/layers/etymology/etymology.json index 4b43c7ac8..3268eb41b 100644 --- a/assets/layers/etymology/etymology.json +++ b/assets/layers/etymology/etymology.json @@ -52,6 +52,10 @@ "helperArgs": [ "name", { + "notInstanceOf": [ + "Q79007", + "Q22698" + ], "removePostfixes": [ "steenweg", "heirbaan", @@ -70,7 +74,9 @@ "wegel", "kerk", "church", - "kaai" + "kaai", + "park", + "parque" ] } ] @@ -140,7 +146,8 @@ "id": "etymology_multi_apply", "render": { "en": "{multi_apply(_same_name_ids, name:etymology:wikidata;name:etymology, Auto-applying data on all segments with the same name, true)}", - "nl": "{multi_apply(_same_name_ids, name:etymology:wikidata;name:etymology, Wijzigingen worden automatisch gedaan op alle segmenten met dezelfde naam, true)}" + "nl": "{multi_apply(_same_name_ids, name:etymology:wikidata;name:etymology, Wijzigingen worden automatisch gedaan op alle segmenten met dezelfde naam, true)}", + "de": "{multi_apply(_same_name_ids, name:etymology:wikidata;name:etymology, Automatische Datenübernahme auf alle Segmente mit demselben Namen, true)}" } }, { diff --git a/assets/layers/extinguisher/extinguisher.json b/assets/layers/extinguisher/extinguisher.json index 47e3ffcb8..541de86c1 100644 --- a/assets/layers/extinguisher/extinguisher.json +++ b/assets/layers/extinguisher/extinguisher.json @@ -6,7 +6,7 @@ "nb_NO": "Kart over brannhydranter", "ru": "Карта огнетушителей.", "fr": "Couche des extincteurs.", - "de": "Feuerlöscher anzeigen", + "de": "Feuerlöscher anzeigen.", "it": "Cartina degli estintori.", "nl": "Kaart van brandblussers." }, @@ -27,7 +27,8 @@ "fr": "Exctincteurs", "de": "Feuerlöscher", "it": "Estintori", - "nl": "Brandblussers" + "nl": "Brandblussers", + "ca": "Extintors" } }, "description": { diff --git a/assets/layers/food/food.json b/assets/layers/food/food.json index 79c0144e9..93294a607 100644 --- a/assets/layers/food/food.json +++ b/assets/layers/food/food.json @@ -20,7 +20,8 @@ "en": "a restaurant", "nl": "een restaurant", "ru": "ресторан", - "de": "eine restaurant" + "de": "eine restaurant", + "ca": "un restaurant" }, "tags": [ "amenity=restaurant" @@ -39,7 +40,8 @@ "en": "a fastfood", "nl": "een fastfood-zaak", "ru": "быстрое питание", - "de": "eine schnellimbiss" + "de": "eine schnellimbiss", + "ca": "un de menjar ràpid" }, "tags": [ "amenity=fast_food" @@ -64,7 +66,7 @@ "cuisine=friture" ], "description": { - "en": "A fastfood-buisiness focused on french fries", + "en": "A fastfood-business focused on french fries", "nl": "Een fastfood-zaak waar je frieten koopt" }, "preciseInput": { @@ -75,7 +77,9 @@ "title": { "render": { "en": "Restaurant", - "nl": "Eetgelegenheid" + "nl": "Eetgelegenheid", + "ca": "Restaurant", + "de": "Restaurant" }, "mappings": [ { @@ -88,7 +92,8 @@ "then": { "nl": "Restaurant {name}", "en": "Restaurant {name}", - "de": "Restaurant {name}" + "de": "Restaurant {name}", + "ca": "Restaurant {name}" } }, { @@ -101,7 +106,8 @@ "then": { "nl": "Fastfood-zaak {name}", "en": "Fastfood {name}", - "de": "Schnellrestaurant{name}" + "de": "Schnellrestaurant{name}", + "ca": "Lloc de menjar ràpid {name}" } }, { @@ -113,7 +119,8 @@ "then": { "nl": "Fastfood-zaak", "en": "Fastfood", - "de": "Schnellrestaurant" + "de": "Schnellrestaurant", + "ca": "Menjar ràpid" } } ] @@ -454,7 +461,8 @@ "question": { "en": "Does this fries shop have vegetarian snacks?", "nl": "Heeft deze frituur vegetarische snacks?", - "fr": "Cette friterie est-elle équipée de snacks végétariens ?" + "fr": "Cette friterie est-elle équipée de snacks végétariens ?", + "de": "Hat dieser Frittenladen vegetarische Snacks?" }, "mappings": [ { @@ -602,7 +610,8 @@ "question": { "en": "Opened now", "nl": "Nu geopened", - "de": "Aktuell geöffnet" + "de": "Aktuell geöffnet", + "ca": "Obert ara" }, "osmTags": "_isOpen=yes" } diff --git a/assets/layers/ghost_bike/ghost_bike.json b/assets/layers/ghost_bike/ghost_bike.json index 22cb70ab2..550daa9c2 100644 --- a/assets/layers/ghost_bike/ghost_bike.json +++ b/assets/layers/ghost_bike/ghost_bike.json @@ -18,7 +18,8 @@ "ru": "Велосипед ghost", "sv": "Spökcykel", "zh_Hant": "幽靈單車", - "pt": "Bicicleta fantasma" + "pt": "Bicicleta fantasma", + "ca": "Bicicleta blanca" }, "source": { "osmTags": "memorial=ghost_bike" @@ -43,7 +44,8 @@ "ru": "Велосипед Ghost", "sv": "Spökcykel", "zh_Hant": "幽靈單車", - "pt": "Bicicleta fantasma" + "pt": "Bicicleta fantasma", + "ca": "Bicicleta blanca" }, "mappings": [ { @@ -123,7 +125,7 @@ "then": { "en": "No name is marked on the bike", "nl": "De naam is niet aangeduid op de fiets", - "de": "Auf dem Fahrrad ist kein Name angegeben", + "de": "Am Fahrrad ist kein Name angegeben", "it": "Nessun nome scritto sulla bici", "fr": "Aucun nom n'est marqué sur le vélo" } @@ -225,6 +227,7 @@ ], "description": { "en": "A layer showing memorials for cyclists, killed in road accidents", - "nl": "Een laag die herdenkingsplaatsen voor verongelukte fietsers toont" + "nl": "Een laag die herdenkingsplaatsen voor verongelukte fietsers toont", + "de": "Eine Ebene mit Gedenkstätten für Radfahrer, die bei Verkehrsunfällen ums Leben gekommen sind" } } \ No newline at end of file diff --git a/assets/layers/gps_track/gps_track.json b/assets/layers/gps_track/gps_track.json index 4e5bdc17a..18a4d83b3 100644 --- a/assets/layers/gps_track/gps_track.json +++ b/assets/layers/gps_track/gps_track.json @@ -15,7 +15,8 @@ "id": "Privacy notice", "render": { "en": "This is the path you've travelled since this website is opened. Don't worry - this is only visible to you and no one else. Your location data is never sent off-device.", - "nl": "Dit is waar je was sinds je deze website hebt geopened. Dit is enkel zichtbaar voor jou en niemand anders, je locatie wordt niet verstuurd" + "nl": "Dit is waar je was sinds je deze website hebt geopened. Dit is enkel zichtbaar voor jou en niemand anders, je locatie wordt niet verstuurd", + "de": "Dies ist der Weg, den Sie seit dem Besuch dieser Webseite zurückgelegt haben. Keine Sorge - diese Daten sind nur für Sie sichtbar und für niemanden sonst. Ihre Standortdaten werden niemals an ein anderes Gerät gesendet." } }, "export_as_gpx", diff --git a/assets/layers/hackerspace/hackerspace.json b/assets/layers/hackerspace/hackerspace.json new file mode 100644 index 000000000..3a360fbbb --- /dev/null +++ b/assets/layers/hackerspace/hackerspace.json @@ -0,0 +1,258 @@ +{ + "id": "hackerspace", + "name": { + "en": "Hackerspace", + "de": "Hackerspaces", + "ru": "Хакерспейс", + "zh_Hant": "駭客空間", + "hu": "Hackerspace" + }, + "minzoom": 8, + "title": { + "render": { + "en": "Hackerspace", + "de": "Hackerspace", + "ru": "Хакерспейс", + "zh_Hant": "駭客空間", + "hu": "Hackerspace" + }, + "mappings": [ + { + "if": { + "and": [ + "name~*" + ] + }, + "then": { + "en": " {name}", + "de": " {name}", + "ru": " {name}", + "zh_Hant": " {name}", + "hu": " {name}", + "ca": " {name}" + } + } + ] + }, + "description": { + "en": "Hackerspace", + "de": "Hackerspace", + "ru": "Хакерспейс", + "zh_Hant": "駭客空間", + "hu": "Hackerspace" + }, + "tagRenderings": [ + { + "id": "is_makerspace", + "question": { + "en": "Is this a hackerspace or a makerspace?", + "de": "Ist dies ein Hackerspace oder ein Makerspace?", + "zh_Hant": "這邊是駭客空間還是創客空間?", + "hu": "Ez hackerspace vagy makerspace?" + }, + "mappings": [ + { + "if": "hackerspace=makerspace", + "then": { + "en": "This is a makerspace", + "de": "Dies ist ein Makerspace", + "zh_Hant": "這是創客空間", + "hu": "Ez egy makerspace" + } + }, + { + "if": "hackerspace=", + "then": { + "en": "This is a traditional (software oriented) hackerspace", + "de": "Dies ist ein traditioneller (softwareorientierter) Hackerspace", + "zh_Hant": "這是傳統的 (軟體導向) 駭客空間", + "hu": "Ez egy hagyományos (szoftverekkel foglalkozó) hackerspace" + } + } + ] + }, + { + "question": { + "en": "What is the name of this hackerspace?", + "de": "Wie lautet der Name dieses Hackerspace?", + "zh_Hant": "這個駭客空間的名稱是?" + }, + "render": { + "en": "This hackerspace is named {name}", + "de": "Dieser Hackerspace heißt {name}", + "zh_Hant": "這個駭客空間叫 {name}" + }, + "freeform": { + "key": "name" + }, + "id": "hackerspaces-name" + }, + "website", + "email", + "phone", + { + "question": { + "en": "When is this hackerspace opened?", + "de": "Wann hat dieser Hackerspace geöffnet?", + "zh_Hant": "這個駭客空間的營業時間?" + }, + "freeform": { + "key": "opening_hours", + "type": "opening_hours" + }, + "render": { + "en": "{opening_hours_table()}", + "de": "{opening_hours_table()}", + "ru": "{opening_hours_table()}", + "zh_Hant": "{opening_hours_table()}", + "ca": "{opening_hours_table()}" + }, + "mappings": [ + { + "if": { + "and": [ + "opening_hours=24/7" + ] + }, + "then": { + "en": "Opened 24/7", + "de": "durchgehend geöffnet", + "ru": "Открыто 24/7", + "zh_Hant": "24/7 營業", + "ca": "Obert 24/7" + } + } + ], + "id": "hackerspaces-opening_hours" + }, + "wheelchair-access", + { + "id": "hs-club-mate", + "question": { + "en": "Does this hackerspace serve Club Mate?", + "de": "Gibt es in diesem Hackerspace Club Mate?", + "zh_Hant": "這個駭客空間是否服務俱樂部伙伴?" + }, + "mappings": [ + { + "if": { + "and": [ + "drink:club-mate=yes" + ] + }, + "then": { + "en": "This hackerspace serves club mate", + "de": "In diesem Hackerspace gibt es Club Mate", + "zh_Hant": "這個駭客空間服務俱樂部伙伴" + } + }, + { + "if": { + "and": [ + "drink:club-mate=no" + ] + }, + "then": { + "en": "This hackerspace does not serve club mate", + "de": "In diesem Hackerspace gibt es kein Club Mate", + "zh_Hant": "這個駭客空間沒有服務俱樂部伙伴" + } + } + ] + }, + { + "render": { + "en": "This hackerspace was founded at {start_date}", + "de": "Dieser Hackerspace wurde gegründet am {start_date}", + "zh_Hant": "這駭客空間是 {start_date} 成立的" + }, + "question": { + "en": "When was this hackerspace founded?", + "de": "Wann wurde dieser Hackerspace gegründet?", + "zh_Hant": "這個駭客空間何時成立的?" + }, + "freeform": { + "key": "start_date", + "type": "date" + }, + "id": "hackerspaces-start_date" + } + ], + "presets": [ + { + "tags": [ + "leisure=hackerspace" + ], + "title": { + "en": "a hackerspace", + "de": "eine hackerspace", + "ru": "Хакерспейс", + "zh_Hant": "駭客空間", + "hu": "Hackerspace" + }, + "description": { + "en": "A hackerspace is an area where people interested in software gather", + "de": "Ein Hackerspace ist ein Ort, an dem sich Menschen treffen, die sich für Software interessieren", + "zh_Hant": "駭客空間是對軟體有興趣的人聚集的地方", + "hu": "A hackerspace egy olyan hely, ahol szoftverek iránt érdeklő emberek találkoznak" + } + }, + { + "tags": [ + "leisure=hackerspace", + "hackerspace=makerspace" + ], + "title": { + "en": "a makerspace", + "de": "eine makerspace", + "zh_Hant": "創客空間", + "hu": "Makerspace" + }, + "description": { + "en": "A makerspace is a place where DIY-enthusiasts gather to experiment with electronics such as arduino, LEDstrips, ...", + "de": "Ein Makerspace ist ein Ort, an dem Heimwerker-Enthusiasten zusammenkommen, um mit Elektronik zu experimentieren, wie Arduino, LED-Strips, ...", + "zh_Hant": "創客空間是 DIY 愛好者聚集在一起弄電子零件實驗,例如用 arduino、LEDstrips 等...", + "hu": "A makerspace olyan hely, ahol a barkácsolás szerelmesei találkoznak, hogy olyan elektronikai eszközökkel kísérletezzenek, mint például az Arduino vagy a LEDstrips." + } + } + ], + "source": { + "osmTags": { + "and": [ + "leisure=hackerspace" + ] + } + }, + "mapRendering": [ + { + "icon": { + "render": "./assets/themes/hackerspaces/glider.svg", + "mappings": [ + { + "if": { + "and": [ + "hackerspace=makerspace" + ] + }, + "then": "./assets/themes/hackerspaces/led.png" + } + ] + }, + "iconSize": { + "render": "40,40,center" + }, + "location": [ + "point", + "centroid" + ] + }, + { + "color": { + "render": "#00f" + }, + "width": { + "render": "8" + } + } + ] +} \ No newline at end of file diff --git a/assets/layers/hydrant/hydrant.json b/assets/layers/hydrant/hydrant.json index bf26bc6e1..7d1c6a894 100644 --- a/assets/layers/hydrant/hydrant.json +++ b/assets/layers/hydrant/hydrant.json @@ -28,7 +28,8 @@ "fr": "Bornes incendie", "de": "Hydrant", "it": "Idrante", - "nl": "Brandkraan" + "nl": "Brandkraan", + "ca": "Hidrant" } }, "description": { diff --git a/assets/layers/information_board/information_board.json b/assets/layers/information_board/information_board.json index 514778bb1..ed9fe7e11 100644 --- a/assets/layers/information_board/information_board.json +++ b/assets/layers/information_board/information_board.json @@ -6,7 +6,8 @@ "it": "Pannelli informativi", "fr": "Panneaux d'informations", "de": "Informationstafeln", - "ru": "Информационные щиты" + "ru": "Информационные щиты", + "ca": "Panells d'informació" }, "minzoom": 12, "source": { @@ -23,7 +24,8 @@ "it": "Pannello informativo", "fr": "Panneau d'informations", "de": "Informationstafel", - "ru": "Информационный щит" + "ru": "Информационный щит", + "ca": "Panell d'informació" } }, "tagRenderings": [ @@ -80,6 +82,7 @@ ], "description": { "en": "A layer showing touristical, road side information boards (e.g. giving information about the landscape, a building, a feature, a map, ...)", - "nl": "Deze laag toont informatieborden in de publieke ruimte die uitleg geven over een bezienswaardigheid (bv. uitleg over het landschap, een ruine, een kaart van de omgeving, ...)" + "nl": "Deze laag toont informatieborden in de publieke ruimte die uitleg geven over een bezienswaardigheid (bv. uitleg over het landschap, een ruine, een kaart van de omgeving, ...)", + "de": "Eine Ebene mit touristischen, straßenseitigen Informationstafeln (z. B. mit Informationen über die Landschaft, ein Gebäude, ein Merkmal, eine Karte, ...)" } } \ No newline at end of file diff --git a/assets/layers/map/map.json b/assets/layers/map/map.json index 163a4d031..09804d41d 100644 --- a/assets/layers/map/map.json +++ b/assets/layers/map/map.json @@ -6,7 +6,8 @@ "it": "Mappe", "ru": "Карты", "fr": "Cartes", - "de": "Karten" + "de": "Karten", + "ca": "Mapes" }, "minzoom": 12, "source": { @@ -24,7 +25,8 @@ "it": "Mappa", "ru": "Карта", "fr": "Carte", - "de": "Karte" + "de": "Karte", + "ca": "Mapa" } }, "description": { @@ -177,7 +179,8 @@ "it": "una mappa", "ru": "Карта", "fr": "une carte", - "de": "eine karte" + "de": "eine karte", + "ca": "un mapa" }, "description": { "en": "Add a missing map", diff --git a/assets/layers/nature_reserve/nature_reserve.json b/assets/layers/nature_reserve/nature_reserve.json index 4dee1cdff..6c4db4dcf 100644 --- a/assets/layers/nature_reserve/nature_reserve.json +++ b/assets/layers/nature_reserve/nature_reserve.json @@ -26,7 +26,8 @@ "title": { "render": { "nl": "Natuurgebied", - "en": "Nature reserve" + "en": "Nature reserve", + "de": "Naturschutzgebiet" }, "mappings": [ { @@ -51,11 +52,13 @@ { "render": { "en": "Accessin this nature reserve: {access:description}", - "nl": "De toegankelijkheid van dit gebied is: {access:description}" + "nl": "De toegankelijkheid van dit gebied is: {access:description}", + "de": "Zugang zu diesem Naturschutzgebiet: {access:description}" }, "question": { "en": "Is this nature reserve accessible to the public?", - "nl": "Is dit gebied toegankelijk?" + "nl": "Is dit gebied toegankelijk?", + "de": "Ist dieses Naturschutzgebiet für die Öffentlichkeit zugänglich?" }, "freeform": { "key": "access:description" @@ -70,7 +73,8 @@ }, "then": { "en": "Publicly accessible", - "nl": "Vrij toegankelijk" + "nl": "Vrij toegankelijk", + "de": "Öffentlich zugänglich" } }, { @@ -82,7 +86,8 @@ }, "then": { "en": "Not accessible", - "nl": "Niet toegankelijk" + "nl": "Niet toegankelijk", + "de": "Nicht zugänglich" } }, { @@ -94,7 +99,8 @@ }, "then": { "en": "Not accessible as this is a private area", - "nl": "Niet toegankelijk, want privégebied" + "nl": "Niet toegankelijk, want privégebied", + "de": "Nicht zugänglich, da dies ein privater Bereich ist" } }, { @@ -106,7 +112,8 @@ }, "then": { "en": "Accessible despite being a privately owned area", - "nl": "Toegankelijk, ondanks dat het privegebied is" + "nl": "Toegankelijk, ondanks dat het privegebied is", + "de": "Zugänglich, obwohl es sich um ein privates Gebiet handelt" } }, { @@ -118,7 +125,8 @@ }, "then": { "en": "Only accessible with a guide or during organised activities", - "nl": "Enkel toegankelijk met een gids of tijdens een activiteit" + "nl": "Enkel toegankelijk met een gids of tijdens een activiteit", + "de": "Nur mit einem Führer oder bei organisierten Aktivitäten zugänglich" } }, { @@ -130,7 +138,8 @@ }, "then": { "en": "Accessible with fee", - "nl": "Toegankelijk mits betaling" + "nl": "Toegankelijk mits betaling", + "de": "Zugänglich gegen Gebühr" } } ], @@ -139,11 +148,13 @@ { "render": { "en": "Operated by {operator}", - "nl": "Beheer door {operator}" + "nl": "Beheer door {operator}", + "de": "Betrieben von {operator}" }, "question": { "en": "Who operates this area?", - "nl": "Wie beheert dit gebied?" + "nl": "Wie beheert dit gebied?", + "de": "Wer betreibt dieses Gebiet?" }, "freeform": { "key": "operator" @@ -157,7 +168,8 @@ }, "then": { "en": "Operated by Natuurpunt", - "nl": "Dit gebied wordt beheerd door Natuurpunt" + "nl": "Dit gebied wordt beheerd door Natuurpunt", + "de": "Betrieben von Natuurpunt" }, "icon": "./assets/layers/nature_reserve/Natuurpunt.jpg" }, @@ -169,7 +181,8 @@ }, "then": { "en": "Operated by {operator}", - "nl": "Dit gebied wordt beheerd door {operator}" + "nl": "Dit gebied wordt beheerd door {operator}", + "de": "Betrieben von {operator}" }, "icon": "./assets/layers/nature_reserve/Natuurpunt.jpg", "hideInAnswer": true @@ -182,7 +195,8 @@ }, "then": { "en": "Operated by Agentschap Natuur en Bos", - "nl": "Dit gebied wordt beheerd door het Agentschap Natuur en Bos" + "nl": "Dit gebied wordt beheerd door het Agentschap Natuur en Bos", + "de": "Betrieben von Agentschap Natuur en Bos" }, "icon": "./assets/layers/nature_reserve/ANB.jpg" } @@ -192,11 +206,13 @@ { "render": { "nl": "Dit gebied heet {name}", - "en": "This area is named {name}" + "en": "This area is named {name}", + "de": "Dieses Gebiet heißt {name}" }, "question": { "nl": "Wat is de naam van dit gebied?", - "en": "What is the name of this area?" + "en": "What is the name of this area?", + "de": "Wie heißt dieses Gebiet?" }, "freeform": { "key": "name", @@ -219,7 +235,8 @@ }, "then": { "en": "This area doesn't have a name", - "nl": "Dit gebied heeft geen naam" + "nl": "Dit gebied heeft geen naam", + "de": "Dieses Gebiet hat keinen Namen" } } ], @@ -340,7 +357,8 @@ { "render": { "en": "Extra information: {description}", - "nl": "Extra info: {description}" + "nl": "Extra info: {description}", + "de": "Zusätzliche Informationen: {description}" }, "freeform": { "key": "description" @@ -350,11 +368,13 @@ { "question": { "en": "Is there some extra info?", - "nl": "Is er extra info die je kwijt wil?" + "nl": "Is er extra info die je kwijt wil?", + "de": "Gibt es zusätzliche Informationen?" }, "render": { "en": "Extra info: {description:0}", - "nl": "Extra info: {description:0}" + "nl": "Extra info: {description:0}", + "de": "Zusätzliche Informationen: {description:0}" }, "freeform": { "key": "description:0" @@ -382,11 +402,13 @@ ], "title": { "en": "a nature reserve", - "nl": "een natuurreservaat" + "nl": "een natuurreservaat", + "de": "ein Naturschutzgebiet" }, "description": { "en": "Add a missing nature reserve", - "nl": "Voeg een ontbrekend, erkend natuurreservaat toe, bv. een gebied dat beheerd wordt door het ANB of natuurpunt" + "nl": "Voeg een ontbrekend, erkend natuurreservaat toe, bv. een gebied dat beheerd wordt door het ANB of natuurpunt", + "de": "Ein fehlendes Naturschutzgebiet hinzufügen" } } ], @@ -410,7 +432,8 @@ { "question": { "en": "All nature reserves", - "nl": "Alle natuurgebieden" + "nl": "Alle natuurgebieden", + "de": "Alle Naturschutzgebiete" } }, { diff --git a/assets/layers/note/note.json b/assets/layers/note/note.json index e5b1be20e..1a64adbac 100644 --- a/assets/layers/note/note.json +++ b/assets/layers/note/note.json @@ -16,14 +16,17 @@ "title": { "render": { "en": "Note", - "nl": "Note" + "nl": "Note", + "ca": "Nota", + "de": "Notiz" }, "mappings": [ { "if": "closed_at~*", "then": { "en": "Closed note", - "nl": "Gesloten Note" + "nl": "Gesloten Note", + "de": "Geschlossene Notiz" } } ] @@ -60,7 +63,8 @@ "id": "report-contributor", "render": { "en": "Report {_first_user} as spam", - "nl": "{_first_user} melden als spam" + "nl": "{_first_user} melden als spam", + "de": "{_first_user} als Spam melden" }, "condition": "_opened_by_anonymous_user=false" }, @@ -68,7 +72,8 @@ "id": "report-note", "render": { "en": "Report this note as spam or inappropriate", - "nl": "Deze not melden als spam of ongepast" + "nl": "Deze not melden als spam of ongepast", + "de": "Diese Notiz als Spam oder unangemessen melden" } } ], @@ -113,7 +118,8 @@ ], "question": { "en": "Should mention {search} in the first comment", - "nl": "Moet in de eerste opmerking \"{search}\" bevatten" + "nl": "Moet in de eerste opmerking \"{search}\" bevatten", + "de": "Sollte {search} im ersten Kommentar erwähnen" } } ] @@ -130,7 +136,8 @@ ], "question": { "en": "Should not mention {search} in the first comment", - "nl": "Mag in de eerste opmerking niet \"{search}\" bevatten" + "nl": "Mag in de eerste opmerking niet \"{search}\" bevatten", + "de": "Sollte nicht {search} im ersten Kommentar erwähnen" } } ] @@ -147,7 +154,8 @@ ], "question": { "en": "Opened by contributor {search}", - "nl": "Geopend door bijdrager {search}" + "nl": "Geopend door bijdrager {search}", + "de": "Geöffnet vom Mitwirkenden {search}" } } ] @@ -164,7 +172,8 @@ ], "question": { "en": "Not opened by contributor {search}", - "nl": "Niet geopend door bijdrager {search}" + "nl": "Niet geopend door bijdrager {search}", + "de": "Nicht vom Mitwirkenden {search} geöffnet" } } ] @@ -181,7 +190,8 @@ ], "question": { "en": "Last edited by contributor {search}", - "nl": "Laatst bewerkt door bijdrager {search}" + "nl": "Laatst bewerkt door bijdrager {search}", + "de": "Zuletzt bearbeitet vom Mitwirkenden {search}" } } ] @@ -198,7 +208,8 @@ ], "question": { "en": "Opened after {search}", - "nl": "Geopend na {search}" + "nl": "Geopend na {search}", + "de": "Geöffnet nach {search}" } } ] @@ -216,7 +227,8 @@ ], "question": { "en": "Created before {search}", - "nl": "Aangemaakt voor {search}" + "nl": "Aangemaakt voor {search}", + "de": "Erstellt vor {search}" } } ] @@ -234,7 +246,8 @@ ], "question": { "en": "Created after {search}", - "nl": "Aangemaakt na {search}" + "nl": "Aangemaakt na {search}", + "de": "Erstellt nach {search}" } } ] @@ -246,7 +259,8 @@ "osmTags": "_opened_by_anonymous_user=true", "question": { "en": "Only show notes opened by an anonymous contributor", - "nl": "Toon enkel de Notes geopend door een anonieme bijdrager" + "nl": "Toon enkel de Notes geopend door een anonieme bijdrager", + "de": "Nur Notizen anzeigen, die von anonymen Mitwirkenden geöffnet wurden" } } ] @@ -258,7 +272,8 @@ "osmTags": "closed_at=", "question": { "en": "Only show open notes", - "nl": "Toon enkel open Notes" + "nl": "Toon enkel open Notes", + "de": "Nur offene Notizen anzeigen" } } ] @@ -270,7 +285,8 @@ "osmTags": "_is_import_note=", "question": { "en": "Hide import notes", - "nl": "Verberg import Notes" + "nl": "Verberg import Notes", + "de": "Importnotizen ausblenden" } } ] diff --git a/assets/layers/note_import/note_import.json b/assets/layers/note_import/note_import.json index 40d33c32c..72584bed5 100644 --- a/assets/layers/note_import/note_import.json +++ b/assets/layers/note_import/note_import.json @@ -2,7 +2,8 @@ "id": "note_import", "name": { "en": "Possible bookcases", - "nl": "Mogelijke publieke boekenkastjes" + "nl": "Mogelijke publieke boekenkastjes", + "de": "Mögliche Bücherschränke" }, "description": "Template for note note imports.", "source": { @@ -19,7 +20,8 @@ "title": { "render": { "en": "Possible feature", - "nl": "Mogelijk object" + "nl": "Mogelijk object", + "de": "Mögliches Objekt" } }, "calculatedTags": [ diff --git a/assets/layers/observation_tower/observation_tower.json b/assets/layers/observation_tower/observation_tower.json index 662fd09ee..59943038e 100644 --- a/assets/layers/observation_tower/observation_tower.json +++ b/assets/layers/observation_tower/observation_tower.json @@ -4,7 +4,8 @@ "en": "Observation towers", "nl": "Uitkijktorens", "ru": "Смотровые башни", - "de": "Aussichtstürme" + "de": "Aussichtstürme", + "ca": "Torres d'observació" }, "minzoom": 8, "title": { @@ -12,7 +13,8 @@ "en": "Observation tower", "nl": "Uitkijktoren", "ru": "Смотровая башня", - "de": "Beobachtungsturm" + "de": "Beobachtungsturm", + "ca": "Torre d'observació" }, "mappings": [ { @@ -21,7 +23,8 @@ "en": "{name}", "nl": "{name}", "ru": "{name}", - "de": "{name}" + "de": "{name}", + "ca": "{name}" } } ] @@ -81,21 +84,24 @@ "question": { "en": "Can this tower be visited?", "nl": "Is deze toren publiek toegankelijk?", - "es": "¿Se puede visitar esta torre?" + "es": "¿Se puede visitar esta torre?", + "de": "Kann dieser Turm besichtigt werden?" }, "mappings": [ { "if": "access=yes", "then": { "en": "This tower is publicly accessible", - "nl": "Deze toren is publiek toegankelijk" + "nl": "Deze toren is publiek toegankelijk", + "de": "Dieser Turm ist öffentlich zugänglich" } }, { "if": "access=guided", "then": { "en": "This tower can only be visited with a guide", - "nl": "Deze toren can enkel bezocht worden met een gids" + "nl": "Deze toren can enkel bezocht worden met een gids", + "de": "Dieser Turm kann nur mit einem Führer besichtigt werden" } } ] @@ -157,7 +163,8 @@ "id": "step_count", "question": { "en": "How much individual steps does one have to climb to reach the top of this tower?", - "nl": "Hoeveel treden moet men beklimmen op de top van de toren te bereiken?" + "nl": "Hoeveel treden moet men beklimmen op de top van de toren te bereiken?", + "de": "Wie viele einzelne Stufen muss man erklimmen, um die Spitze des Turms zu erreichen?" }, "freeform": { "key": "step_count", @@ -165,7 +172,8 @@ }, "render": { "en": "This tower has {step_count} steps to reach the top", - "nl": "Deze toren heeft {step_count} traptredes" + "nl": "Deze toren heeft {step_count} traptredes", + "de": "Dieser Turm hat {step_count} Stufen, um die Spitze zu erreichen" }, "condition": { "or": [ @@ -178,21 +186,24 @@ "id": "elevator", "question": { "en": "Does this tower have an elevator?", - "nl": "Heeft deze toren een lift?" + "nl": "Heeft deze toren een lift?", + "de": "Hat dieser Turm einen Aufzug?" }, "mappings": [ { "if": "elevator=yes", "then": { "en": "This tower has an elevator which takes visitors to the top", - "nl": "Deze toren heeft een lift die bezoekers naar de top van de toren brengt" + "nl": "Deze toren heeft een lift die bezoekers naar de top van de toren brengt", + "de": "Dieser Turm verfügt über einen Aufzug, der die Besucher nach oben bringt" } }, { "if": "elevator=no", "then": { "en": "This tower does not have an elevator", - "nl": "Deze toren heeft geen lift" + "nl": "Deze toren heeft geen lift", + "de": "Dieser Turm hat keinen Aufzug" } } ], @@ -260,7 +271,8 @@ "nl": " meter", "en": " meter", "ru": " метр", - "de": " Meter" + "de": " Meter", + "ca": " metre" } } ], diff --git a/assets/layers/parking/parking.json b/assets/layers/parking/parking.json index 4804b2d80..17ec106fe 100644 --- a/assets/layers/parking/parking.json +++ b/assets/layers/parking/parking.json @@ -3,7 +3,8 @@ "name": { "en": "Parking", "nl": "Parking", - "de": "Parkplätze" + "de": "Parkplätze", + "ca": "Aparcament" }, "minzoom": 12, "source": { @@ -12,12 +13,14 @@ "title": { "render": { "nl": "Parking voor auto's", - "en": "Car parking" + "en": "Car parking", + "de": "Parkplatz" } }, "description": { "en": "A layer showing car parkings", - "nl": "Deze laag toont autoparkings" + "nl": "Deze laag toont autoparkings", + "de": "Eine Ebene mit Parkplätzen" }, "tagRenderings": [ "images" @@ -29,7 +32,8 @@ ], "title": { "nl": "een parking voor auto's", - "en": "a car parking" + "en": "a car parking", + "de": "ein Parkplatz" } } ], diff --git a/assets/layers/picnic_table/picnic_table.json b/assets/layers/picnic_table/picnic_table.json index c2b6180cb..f38cb6e65 100644 --- a/assets/layers/picnic_table/picnic_table.json +++ b/assets/layers/picnic_table/picnic_table.json @@ -6,7 +6,8 @@ "it": "Tavoli da picnic", "ru": "Столы для пикника", "fr": "Tables de pique-nique", - "de": "Picknick-Tische" + "de": "Picknick-Tische", + "ca": "Taules de pícnic" }, "minzoom": 12, "source": { @@ -19,7 +20,8 @@ "it": "Tavolo da picnic", "ru": "Стол для пикника", "fr": "Table de pique-nique", - "de": "Picknick-Tisch" + "de": "Picknick-Tisch", + "ca": "Taula de pícnic" } }, "description": { diff --git a/assets/layers/playground/playground.json b/assets/layers/playground/playground.json index 2929fc142..ab1693229 100644 --- a/assets/layers/playground/playground.json +++ b/assets/layers/playground/playground.json @@ -6,7 +6,8 @@ "ru": "Детские площадки", "de": "Spielplätze", "it": "Campi da gioco", - "fr": "Aire de jeu" + "fr": "Aire de jeu", + "ca": "Parcs infantils" }, "minzoom": 13, "source": { @@ -26,7 +27,8 @@ "it": "Parchi giochi", "ru": "Детские площадки", "de": "Spielplätze", - "fr": "Aire de jeu" + "fr": "Aire de jeu", + "ca": "Parcs infantils" }, "title": { "render": { @@ -35,7 +37,8 @@ "it": "Parco giochi", "ru": "Детская площадка", "de": "Spielplatz", - "fr": "Aire de jeu" + "fr": "Aire de jeu", + "ca": "Parc infantil" }, "mappings": [ { @@ -46,7 +49,8 @@ "it": "Parco giochi {name}", "ru": "Детская площадка {name}", "de": "Spielplatz {name}", - "fr": "Aire de jeu {name}" + "fr": "Aire de jeu {name}", + "ca": "Parc infantil {name}" } } ] @@ -300,7 +304,8 @@ "if": "fee=yes", "then": { "en": "This is a paid playground", - "nl": "Er moet betaald worden om deze speeltuin te mogen gebruiken" + "nl": "Er moet betaald worden om deze speeltuin te mogen gebruiken", + "de": "Dies ist ein gebührenpflichtiger Spielplatz" }, "addExtraTags": [ "access=customers" @@ -475,7 +480,8 @@ "fr": "Toujours accessible", "ru": "Всегда доступен", "it": "Si può sempre accedere", - "de": "Immer zugänglich" + "de": "Immer zugänglich", + "ca": "Sempre accessible--" } } ], @@ -498,7 +504,8 @@ "ru": "Детская площадка", "fr": "une terrain de jeux", "it": "una campetto", - "de": "eine spielplatz" + "de": "eine spielplatz", + "ca": "un parc infantil" } } ], diff --git a/assets/layers/public_bookcase/public_bookcase.json b/assets/layers/public_bookcase/public_bookcase.json index 959b4d7bf..cb8266826 100644 --- a/assets/layers/public_bookcase/public_bookcase.json +++ b/assets/layers/public_bookcase/public_bookcase.json @@ -7,7 +7,8 @@ "fr": "Microbibliothèque", "ru": "Книжные шкафы", "it": "Microbiblioteche", - "hu": "Könyvespolcok" + "hu": "Könyvespolcok", + "ca": "Bústies per llibres" }, "description": { "en": "A streetside cabinet with books, accessible to anyone", @@ -30,7 +31,8 @@ "fr": "Microbibliothèque", "ru": "Книжный шкаф", "it": "Microbiblioteca", - "hu": "Könyvespolc" + "hu": "Könyvespolc", + "ca": "Bústia per llibres" }, "mappings": [ { @@ -56,7 +58,8 @@ "fr": "une microbibliothèque", "ru": "Книжный шкаф", "it": "una microbiblioteca", - "hu": "Könyvespolc" + "hu": "Könyvespolc", + "ca": "una bústia per a llibres" }, "tags": [ "amenity=public_bookcase" diff --git a/assets/layers/recycling/recycling.json b/assets/layers/recycling/recycling.json index 33de5a3e5..e2078207f 100644 --- a/assets/layers/recycling/recycling.json +++ b/assets/layers/recycling/recycling.json @@ -3,11 +3,13 @@ "name": { "en": "Recycling", "nl": "Recycling", - "de": "Recycling" + "de": "Recycling", + "ca": "Residus" }, "description": { "en": "A layer with recycling containers and centres", - "nl": "Een laag met recyclagingcontainers en -centrums" + "nl": "Een laag met recyclagingcontainers en -centrums", + "de": "Eine Ebene mit Recyclingcontainern und -zentren" }, "source": { "osmTags": "amenity=recycling" @@ -19,7 +21,8 @@ "title": { "render": { "en": "Recycling facility", - "nl": "Recyclingfaciliteit" + "nl": "Recyclingfaciliteit", + "de": "Recyclinganlage" }, "mappings": [ { @@ -27,21 +30,24 @@ "then": { "*": "{name}", "en": "Recycling centre", - "nl": "Recyclingcentrum" + "nl": "Recyclingcentrum", + "de": "Wertstoffhof" } }, { "if": "recycling_type=centre", "then": { "en": "Recycling centre", - "nl": "Recyclingcentrum" + "nl": "Recyclingcentrum", + "de": "Wertstoffhof" } }, { "if": "recycling_type=container", "then": { "en": "Recycling container", - "nl": "Recyclingcontainer" + "nl": "Recyclingcontainer", + "de": "Recyclingcontainer" } } ] @@ -409,7 +415,8 @@ { "title": { "en": "a recycling container", - "nl": "een recycling container" + "nl": "een recycling container", + "de": "ein Recyclingcontainer" }, "tags": [ "amenity=recycling", @@ -419,7 +426,8 @@ { "title": { "en": "a recycling centre", - "nl": "een containerpark (recycling center)" + "nl": "een containerpark (recycling center)", + "de": "ein Wertstoffhof" }, "tags": [ "amenity=recycling", @@ -433,28 +441,32 @@ "id": "recycling-type", "question": { "en": "What type of recycling is this?", - "nl": "Wat voor soort recycling is dit?" + "nl": "Wat voor soort recycling is dit?", + "de": "Um welche Recyclingeinrichtung handelt es sich?" }, "mappings": [ { "if": "recycling_type=container", "then": { "en": "This is a recycling container", - "nl": "Dit is een recyclingcontainer" + "nl": "Dit is een recyclingcontainer", + "de": "Dies ist ein Recycling-Container" } }, { "if": "recycling_type=centre", "then": { "en": "This is a recycling centre", - "nl": "Dit is een recyclingcentrum" + "nl": "Dit is een recyclingcentrum", + "de": "Dies ist ein Wertstoffhof" } }, { "if": "amenity=waste_disposal", "then": { "en": "Waste disposal container for residual waste", - "nl": "Afvalcontainer voor restafval" + "nl": "Afvalcontainer voor restafval", + "de": "Dies ist ein Abfallcontainer für Restmüll" }, "addExtraTags": [ "recycling:batteries=", @@ -485,11 +497,13 @@ "id": "recycling-centre-name", "question": { "en": "What is the name of this recycling centre?", - "nl": "Wat is de naam van dit recyclagecentrum?" + "nl": "Wat is de naam van dit recyclagecentrum?", + "de": "Wie lautet der Name dieses Wertstoffhofs?" }, "render": { "en": "This recycling centre is named {name}", - "nl": "Dit recyclagecentrum heet {name}" + "nl": "Dit recyclagecentrum heet {name}", + "de": "Dieser Wertstoffhof heißt {name}" }, "freeform": { "key": "name" @@ -499,7 +513,8 @@ "if": "noname=yes", "then": { "en": "This recycling centre doesn't have a specific name", - "nl": "Dit recyclagecentrum heeft geen specifieke naam" + "nl": "Dit recyclagecentrum heeft geen specifieke naam", + "de": "Dieser Wertstoffhof hat keinen bestimmten Namen" } } ], @@ -509,7 +524,8 @@ "id": "container-location", "question": { "en": "Where is this container located?", - "nl": "Waar bevindt deze container zich?" + "nl": "Waar bevindt deze container zich?", + "de": "Wo befindet sich dieser Container?" }, "condition": "recycling_type=container", "mappings": [ @@ -517,21 +533,24 @@ "if": "location=underground", "then": { "en": "This is an underground container", - "nl": "Dit is een ondergrondse container" + "nl": "Dit is een ondergrondse container", + "de": "Dies ist ein Unterflurcontainer" } }, { "if": "location=indoor", "then": { "en": "This container is located indoors", - "nl": "Deze container bevindt zich binnen" + "nl": "Deze container bevindt zich binnen", + "de": "Dieser Container befindet sich in einem Gebäude" } }, { "if": "location=", "then": { "en": "This container is located outdoors", - "nl": "Deze container is buiten" + "nl": "Deze container is buiten", + "de": "Dieser Container befindet sich im Freien" } } ] @@ -540,7 +559,8 @@ "id": "recycling-accepts", "question": { "en": "What can be recycled here?", - "nl": "Wat kan hier gerecycled worden?" + "nl": "Wat kan hier gerecycled worden?", + "de": "Was kann hier recycelt werden?" }, "multiAnswer": true, "mappings": [ @@ -549,7 +569,8 @@ "ifnot": "recycling:batteries=", "then": { "en": "Batteries can be recycled here", - "nl": "Batterijen kunnen hier gerecycled worden" + "nl": "Batterijen kunnen hier gerecycled worden", + "de": "Batterien können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/batteries.svg", @@ -561,7 +582,8 @@ "ifnot": "recycling:beverage_cartons=", "then": { "en": "Beverage cartons can be recycled here", - "nl": "Drankpakken kunnen hier gerecycled worden" + "nl": "Drankpakken kunnen hier gerecycled worden", + "de": "Getränkekartons können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/beverage_cartons.svg", @@ -573,7 +595,8 @@ "ifnot": "recycling:cans=", "then": { "en": "Cans can be recycled here", - "nl": "Blikken kunnen hier gerecycled worden" + "nl": "Blikken kunnen hier gerecycled worden", + "de": "Dosen können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/cans.svg", @@ -585,7 +608,8 @@ "ifnot": "recycling:clothes=", "then": { "en": "Clothes can be recycled here", - "nl": "Kleren kunnen hier gerecycled worden" + "nl": "Kleren kunnen hier gerecycled worden", + "de": "Kleidung kann hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/clothes.svg", @@ -597,7 +621,8 @@ "ifnot": "recycling:cooking_oil=", "then": { "en": "Cooking oil can be recycled here", - "nl": "Frituurvet kan hier gerecycled worden" + "nl": "Frituurvet kan hier gerecycled worden", + "de": "Speiseöl kann hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/cooking_oil.svg", @@ -609,7 +634,8 @@ "ifnot": "recycling:engine_oil=", "then": { "en": "Engine oil can be recycled here", - "nl": "Motorolie kan hier gerecycled worden" + "nl": "Motorolie kan hier gerecycled worden", + "de": "Motoröl kann hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/engine_oil.svg", @@ -621,7 +647,8 @@ "ifnot": "recycling:green_waste=", "then": { "en": "Green waste can be recycled here", - "nl": "Groen afval kan hier gerecycled worden" + "nl": "Groen afval kan hier gerecycled worden", + "de": "Grünabfälle können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/garden_waste.svg", @@ -633,7 +660,8 @@ "ifnot": "recycling:organic=", "then": { "en": "Organic waste can be recycled here", - "nl": "Organisch afval kan hier gerecycled worden" + "nl": "Organisch afval kan hier gerecycled worden", + "de": "Bio-Abfall kann hier recycelt werden" }, "hideInAnswer": true, "icon": { @@ -646,7 +674,8 @@ "ifnot": "recycling:glass_bottles=", "then": { "en": "Glass bottles can be recycled here", - "nl": "Glazen flessen kunnen hier gerecycled worden" + "nl": "Glazen flessen kunnen hier gerecycled worden", + "de": "Glasflaschen können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/glass_bottles.svg", @@ -658,7 +687,8 @@ "ifnot": "recycling:glass=", "then": { "en": "Glass can be recycled here", - "nl": "Glas kan hier gerecycled worden" + "nl": "Glas kan hier gerecycled worden", + "de": "Glas kann hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/glass.svg", @@ -670,7 +700,8 @@ "ifnot": "recycling:newspaper=", "then": { "en": "Newspapers can be recycled here", - "nl": "Kranten kunnen hier gerecycled worden" + "nl": "Kranten kunnen hier gerecycled worden", + "de": "Zeitungen können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/newspaper.svg", @@ -682,7 +713,8 @@ "ifnot": "recycling:paper=", "then": { "en": "Paper can be recycled here", - "nl": "Papier kan hier gerecycled worden" + "nl": "Papier kan hier gerecycled worden", + "de": "Papier kann hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/paper.svg", @@ -694,7 +726,8 @@ "ifnot": "recycling:plastic_bottles=", "then": { "en": "Plastic bottles can be recycled here", - "nl": "Plastic flessen kunnen hier gerecycled worden" + "nl": "Plastic flessen kunnen hier gerecycled worden", + "de": "Plastikflaschen können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/plastic_bottles.svg", @@ -706,7 +739,8 @@ "ifnot": "recycling:plastic_packaging=", "then": { "en": "Plastic packaging can be recycled here", - "nl": "Plastic verpakking kan hier gerecycled worden" + "nl": "Plastic verpakking kan hier gerecycled worden", + "de": "Kunststoffverpackungen können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/plastic_packaging.svg", @@ -718,7 +752,8 @@ "ifnot": "recycling:plastic=", "then": { "en": "Plastic can be recycled here", - "nl": "Plastic kan hier gerecycled worden" + "nl": "Plastic kan hier gerecycled worden", + "de": "Kunststoff kann hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/plastic.svg", @@ -730,7 +765,8 @@ "ifnot": "recycling:scrap_metal=", "then": { "en": "Scrap metal can be recycled here", - "nl": "Oud metaal kan hier gerecycled worden" + "nl": "Oud metaal kan hier gerecycled worden", + "de": "Metallschrott kann hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/scrap_metal.svg", @@ -742,7 +778,8 @@ "ifnot": "recycling:shoes=", "then": { "en": "Shoes can be recycled here", - "nl": "Schoenen kunnen hier gerecycled worden" + "nl": "Schoenen kunnen hier gerecycled worden", + "de": "Schuhe können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/shoes.svg", @@ -754,7 +791,8 @@ "ifnot": "recycling:small_appliances=", "then": { "en": "Small electrical appliances can be recycled here", - "nl": "Kleine elektrische apparaten kunnen hier gerecycled worden" + "nl": "Kleine elektrische apparaten kunnen hier gerecycled worden", + "de": "Elektrokleingeräte können hier recycelt werden" }, "icon": { "path": "./assets/layers/recycling/small_electrical_appliances.svg", @@ -766,7 +804,8 @@ "ifnot": "recycling:small_electrical_appliances=", "then": { "en": "Small electrical appliances can be recycled here", - "nl": "Kleine elektrische apparaten kunnen hier gerecycled worden" + "nl": "Kleine elektrische apparaten kunnen hier gerecycled worden", + "de": "Elektrokleingeräte können hier recycelt werden" }, "hideInAnswer": true, "icon": { @@ -779,7 +818,8 @@ "ifnot": "recycling:needles=", "then": { "en": "Needles can be recycled here", - "nl": "Injectienaalden kunnen hier gerecycled worden" + "nl": "Injectienaalden kunnen hier gerecycled worden", + "de": "Nadeln können hier recycelt werden" } }, { @@ -787,7 +827,8 @@ "ifnot": "recycling:waste=", "then": { "en": "Residual waste can be recycled here", - "nl": "Restafval kan hier gerecycled worden" + "nl": "Restafval kan hier gerecycled worden", + "de": "Restmüll kann hier recycelt werden" }, "icon": { "path": "./assets/layers/waste_disposal/waste_disposal.svg", @@ -801,11 +842,13 @@ "id": "operator", "render": { "en": "This recycling facility is operated by {operator}", - "nl": "Deze recyclingfaciliteit wordt beheerd door {operator}" + "nl": "Deze recyclingfaciliteit wordt beheerd door {operator}", + "de": "Diese Recyclinganlage wird betrieben von {operator}" }, "question": { "en": "What company operates this recycling facility?", - "nl": "Wat is de beheerder van deze recyclingfaciliteit?" + "nl": "Wat is de beheerder van deze recyclingfaciliteit?", + "de": "Welches Unternehmen betreibt diese Recyclinganlage?" }, "freeform": { "key": "operator", @@ -827,7 +870,8 @@ "render": "{opening_hours_table()}", "question": { "en": "What are the opening hours of this recycling facility?", - "nl": "Wat zijn de openingstijden van deze recyclingfaciliteit?" + "nl": "Wat zijn de openingstijden van deze recyclingfaciliteit?", + "de": "Wie sind die Öffnungszeiten dieser Recyclinganlage?" }, "freeform": { "key": "opening_hours", @@ -838,7 +882,9 @@ "if": "opening_hours=24/7", "then": { "en": "24/7", - "nl": "24/7" + "nl": "24/7", + "ca": "24/7", + "de": "24/7" } } ] @@ -864,55 +910,63 @@ { "question": { "en": "All recycling types", - "nl": "Alle recyclingtypes" + "nl": "Alle recyclingtypes", + "de": "Alle Recyclingarten" } }, { "question": { "en": "Recycling of batteries", - "nl": "Recycling van batterijen" + "nl": "Recycling van batterijen", + "de": "Recycling von Batterien" }, "osmTags": "recycling:batteries=yes" }, { "question": { "en": "Recycling of beverage cartons", - "nl": "Recycling van drankpakken" + "nl": "Recycling van drankpakken", + "de": "Recycling von Getränkekartons" }, "osmTags": "recycling:beverage_cartons=yes" }, { "question": { "en": "Recycling of cans", - "nl": "Recycling van blikken" + "nl": "Recycling van blikken", + "de": "Recycling von Dosen" }, "osmTags": "recycling:cans=yes" }, { "question": { "en": "Recycling of clothes", - "nl": "Recycling van kleding" + "nl": "Recycling van kleding", + "de": "Recycling von Kleidung" }, "osmTags": "recycling:clothes=yes" }, { "question": { "en": "Recycling of cooking oil", - "nl": "Recycling van frituurvet" + "nl": "Recycling van frituurvet", + "de": "Recycling von Speiseöl" }, "osmTags": "recycling:cooking_oil=yes" }, { "question": { "en": "Recycling of engine oil", - "nl": "Recycling van motorolie" + "nl": "Recycling van motorolie", + "de": "Recycling von Motoröl" }, "osmTags": "recycling:engine_oil=yes" }, { "question": { "en": "Recycling of green waste", - "nl": "Recycling van groen afval" + "nl": "Recycling van groen afval", + "de": "Recycling von Grünabfällen" }, "osmTags": { "or": [ @@ -924,63 +978,72 @@ { "question": { "en": "Recycling of glass bottles", - "nl": "Recycling van glazen flessen" + "nl": "Recycling van glazen flessen", + "de": "Recycling von Glasflaschen" }, "osmTags": "recycling:glass_bottles=yes" }, { "question": { "en": "Recycling of glass", - "nl": "Recycling van glas" + "nl": "Recycling van glas", + "de": "Recycling von Glas" }, "osmTags": "recycling:glass=yes" }, { "question": { "en": "Recycling of newspapers", - "nl": "Recycling van kranten" + "nl": "Recycling van kranten", + "de": "Recycling von Zeitungen" }, "osmTags": "recycling:newspaper=yes" }, { "question": { "en": "Recycling of paper", - "nl": "Recycling van papier" + "nl": "Recycling van papier", + "de": "Recycling von Papier" }, "osmTags": "recycling:paper=yes" }, { "question": { "en": "Recycling of plastic bottles", - "nl": "Recycling van plastic flessen" + "nl": "Recycling van plastic flessen", + "de": "Recycling von Plastikflaschen" }, "osmTags": "recycling:plastic_bottles=yes" }, { "question": { "en": "Recycling of plastic packaging", - "nl": "Recycling van plastic verpakking" + "nl": "Recycling van plastic verpakking", + "de": "Recycling von Kunststoffverpackungen" }, "osmTags": "recycling:plastic_packaging=yes" }, { "question": { "en": "Recycling of plastic", - "nl": "Recycling van plastic" + "nl": "Recycling van plastic", + "de": "Recycling von Kunststoffen" }, "osmTags": "recycling:plastic=yes" }, { "question": { "en": "Recycling of scrap metal", - "nl": "Recycling van oud metaal" + "nl": "Recycling van oud metaal", + "de": "Recycling von Metallschrott" }, "osmTags": "recycling:scrap_metal=yes" }, { "question": { "en": "Recycling of small electrical appliances", - "nl": "Recycling van kleine elektrische apparaten" + "nl": "Recycling van kleine elektrische apparaten", + "de": "Recycling von Elektrokleingeräten" }, "osmTags": { "or": [ @@ -992,7 +1055,8 @@ { "question": { "en": "Recycling of residual waste", - "nl": "Recycling van restafval" + "nl": "Recycling van restafval", + "de": "Recycling von Restabfällen" }, "osmTags": "recycling:waste=yes" } diff --git a/assets/layers/shops/shops.json b/assets/layers/shops/shops.json index adb2ed7a6..a6990c56d 100644 --- a/assets/layers/shops/shops.json +++ b/assets/layers/shops/shops.json @@ -7,7 +7,8 @@ "ja": "店", "nl": "Winkel", "de": "Geschäfte", - "eo": "Butiko" + "eo": "Butiko", + "ca": "Botiga" }, "minzoom": 16, "source": { @@ -25,7 +26,8 @@ "ja": "店", "nl": "Winkel", "de": "Geschäft", - "eo": "Butiko" + "eo": "Butiko", + "ca": "Botiga" }, "mappings": [ { @@ -41,7 +43,8 @@ "ja": "{name}", "de": "{name}", "eo": "{name}", - "nl": "{name}" + "nl": "{name}", + "ca": "{name}" } }, { @@ -57,7 +60,8 @@ "ja": "{shop}", "de": "{shop}", "eo": "{shop}", - "nl": "{shop}" + "nl": "{shop}", + "ca": "{shop}" } } ] @@ -136,7 +140,8 @@ "ru": "Супермаркет", "ja": "スーパーマーケット", "nl": "Supermarkt", - "de": "Supermarkt" + "de": "Supermarkt", + "ca": "Supermercat" } }, { @@ -166,7 +171,8 @@ "ru": "Парикмахерская", "ja": "理容師", "nl": "Kapper", - "de": "Friseur" + "de": "Friseur", + "ca": "Perruqueria" } }, { @@ -181,7 +187,8 @@ "ja": "ベーカリー", "nl": "Bakkerij", "de": "Bäckerei", - "eo": "Bakejo" + "eo": "Bakejo", + "ca": "Fleca" } }, { @@ -287,7 +294,8 @@ "ru": "{email}", "ja": "{email}", "eo": "{email}", - "nl": "{email}" + "nl": "{email}", + "de": "{email}" }, "question": { "en": "What is the email address of this shop?", @@ -310,7 +318,9 @@ "fr": "{opening_hours_table(opening_hours)}", "ru": "{opening_hours_table(opening_hours)}", "ja": "{opening_hours_table(opening_hours)}", - "nl": "{opening_hours_table(opening_hours)}" + "nl": "{opening_hours_table(opening_hours)}", + "ca": "{opening_hours_table(opening_hours)}", + "de": "{opening_hours_table(opening_hours)}" }, "question": { "en": "What are the opening hours of this shop?", @@ -366,7 +376,8 @@ { "explanation": { "nl": "{title()} is permanent gestopt", - "en": "{title()} has closed down permanently" + "en": "{title()} has closed down permanently", + "de": "{title()} wurde dauerhaft geschlossen" }, "changesetMessage": "shop_closed" } @@ -423,7 +434,8 @@ "osmTags": "shop~^.*{search}.*$", "question": { "en": "Only show shops selling {search}", - "de": "Nur Geschäfte, die {search} verkaufen" + "de": "Nur Geschäfte, die {search} verkaufen", + "nl": "Toon enkel winkels die {search} verkopen" } } ] @@ -441,7 +453,8 @@ "osmTags": "name~^.*{search}.*$", "question": { "en": "Only show shops with name {search}", - "de": "Nur Geschäfte mit dem Namen {search} anzeigen" + "de": "Nur Geschäfte mit dem Namen {search} anzeigen", + "nl": "Toon enkel winkels met naam {search}" } } ] diff --git a/assets/layers/slow_roads/slow_roads.json b/assets/layers/slow_roads/slow_roads.json index 1779abcb0..0e0a86b50 100644 --- a/assets/layers/slow_roads/slow_roads.json +++ b/assets/layers/slow_roads/slow_roads.json @@ -281,6 +281,7 @@ ], "description": { "en": "All carfree roads", - "nl": "Alle verkeersvrije wegen" + "nl": "Alle verkeersvrije wegen", + "de": "Alle autofreien Straßen" } } \ No newline at end of file diff --git a/assets/layers/sport_pitch/sport_pitch.json b/assets/layers/sport_pitch/sport_pitch.json index 223ebdb5b..35a658f5f 100644 --- a/assets/layers/sport_pitch/sport_pitch.json +++ b/assets/layers/sport_pitch/sport_pitch.json @@ -6,7 +6,8 @@ "en": "Sport pitches", "ru": "Спортивные площадки", "it": "Campi sportivi", - "de": "Sportplätze" + "de": "Sportplätze", + "ca": "Camps d'esports" }, "minzoom": 12, "source": { @@ -26,7 +27,8 @@ "en": "Sport pitch", "ru": "Спортивная площадка", "it": "Campo sportivo", - "de": "Sportplatz" + "de": "Sportplatz", + "ca": "Camp d'esports" } }, "description": { diff --git a/assets/layers/street_lamps/street_lamps.json b/assets/layers/street_lamps/street_lamps.json index 4bbd7d1c3..5d65a0fa6 100644 --- a/assets/layers/street_lamps/street_lamps.json +++ b/assets/layers/street_lamps/street_lamps.json @@ -12,14 +12,16 @@ "title": { "render": { "en": "Street Lamp", - "nl": "Straatlantaarn" + "nl": "Straatlantaarn", + "de": "Straßenlaterne" }, "mappings": [ { "if": "ref~*", "then": { "en": "Street Lamp {ref}", - "nl": "Straatlantaarn {ref}" + "nl": "Straatlantaarn {ref}", + "de": "Straßenlaterne {ref}" } } ] @@ -44,7 +46,8 @@ { "title": { "en": "a street lamp", - "nl": "een straatlantaarn" + "nl": "een straatlantaarn", + "de": "eine Straßenlaterne" }, "tags": [ "highway=street_lamp" @@ -57,11 +60,13 @@ "id": "ref", "render": { "en": "This street lamp has the reference number {ref}", - "nl": "Deze straatlantaarn heeft het nummer {ref}" + "nl": "Deze straatlantaarn heeft het nummer {ref}", + "de": "Diese Straßenlaterne hat die Referenznummer {ref}" }, "question": { "en": "What is the reference number of this street lamp?", - "nl": "Wat is het nummer van deze straatlantaarn?" + "nl": "Wat is het nummer van deze straatlantaarn?", + "de": "Wie lautet die Referenznummer dieser Straßenlaterne?" }, "freeform": { "key": "ref" @@ -71,56 +76,64 @@ "id": "support", "question": { "en": "How is this street lamp mounted?", - "nl": "Hoe is deze straatlantaarn gemonteerd?" + "nl": "Hoe is deze straatlantaarn gemonteerd?", + "de": "Wie ist diese Straßenlaterne befestigt?" }, "mappings": [ { "if": "support=catenary", "then": { "en": "This lamp is suspended using cables", - "nl": "Deze lantaarn hangt aan kabels" + "nl": "Deze lantaarn hangt aan kabels", + "de": "Diese Straßenlaterne ist an einem Kabel aufgehängt" } }, { "if": "support=ceiling", "then": { "en": "This lamp is mounted on a ceiling", - "nl": "Deze lantaarn hangt aan een plafond" + "nl": "Deze lantaarn hangt aan een plafond", + "de": "Diese Straßenlaterne ist an einer Decke montiert" } }, { "if": "support=ground", "then": { "en": "This lamp is mounted in the ground", - "nl": "Deze lantaarn zit in de grond" + "nl": "Deze lantaarn zit in de grond", + "de": "Diese Straßenlaterne ist im Boden montiert" } }, { "if": "support=pedestal", "then": { "en": "This lamp is mounted on a short pole (mostly < 1.5m)", - "nl": "Deze lantaarn zit op een korte paal (meestal < 1.5m)" + "nl": "Deze lantaarn zit op een korte paal (meestal < 1.5m)", + "de": "Diese Straßenlaterne ist an einem kurzen Mast (< 1,5m) montiert" } }, { "if": "support=pole", "then": { "en": "This lamp is mounted on a pole", - "nl": "Deze lantaarn zit op een paal" + "nl": "Deze lantaarn zit op een paal", + "de": "Diese Straßenlaterne ist an einem Mast montiert" } }, { "if": "support=wall", "then": { "en": "This lamp is mounted directly to the wall", - "nl": "Deze lantaarn hangt direct aan de muur" + "nl": "Deze lantaarn hangt direct aan de muur", + "de": "Diese Straßenlaterne ist direkt an der Wand montiert" } }, { "if": "support=wall_mount", "then": { "en": "This lamp is mounted to the wall using a metal bar", - "nl": "Deze lantaarn hangt aan de muur met een metalen balk" + "nl": "Deze lantaarn hangt aan de muur met een metalen balk", + "de": "Diese Straßenlaterne ist mit einer Metallstange an der Wand montiert" } } ] @@ -129,7 +142,8 @@ "id": "lamp_mount", "question": { "en": "How is this lamp mounted to the pole?", - "nl": "Hoe zit deze lantaarn aan de paal?" + "nl": "Hoe zit deze lantaarn aan de paal?", + "de": "Wie ist diese Straßenlaterne am Mast befestigt?" }, "condition": "support=pole", "mappings": [ @@ -137,14 +151,16 @@ "if": "lamp_mount=straight_mast", "then": { "en": "This lamp sits atop of a straight mast", - "nl": "Deze lantaarn zit boven op een rechte paal" + "nl": "Deze lantaarn zit boven op een rechte paal", + "de": "Diese Straßenlaterne sitzt auf einem geraden Mast" } }, { "if": "lamp_mount=bent_mast", "then": { "en": "This lamp sits at the end of a bent mast", - "nl": "Deze lantaarn zit aan het eind van een gebogen paal" + "nl": "Deze lantaarn zit aan het eind van een gebogen paal", + "de": "Diese Straßenlaterne sitzt am Ende eines gebogenen Mastes" } } ] @@ -153,14 +169,16 @@ "id": "method", "question": { "en": "What kind of lighting does this lamp use?", - "nl": "Wat voor verlichting gebruikt deze lantaarn?" + "nl": "Wat voor verlichting gebruikt deze lantaarn?", + "de": "Mit welcher Art von Beleuchtung arbeitet diese Straßenlaterne?" }, "mappings": [ { "if": "light:method=electric", "then": { "en": "This lamp is lit electrically", - "nl": "Deze lantaarn is elektrisch verlicht" + "nl": "Deze lantaarn is elektrisch verlicht", + "de": "Diese Straßenlaterne leuchtet elektrisch" }, "hideInAnswer": true }, @@ -168,77 +186,88 @@ "if": "light:method=LED", "then": { "en": "This lamp uses LEDs", - "nl": "Deze lantaarn gebruikt LEDs" + "nl": "Deze lantaarn gebruikt LEDs", + "de": "Diese Straßenlaterne verwendet LEDs" } }, { "if": "light:method=incandescent", "then": { "en": "This lamp uses incandescent lighting", - "nl": "Deze lantaarn gebruikt gloeilampen" + "nl": "Deze lantaarn gebruikt gloeilampen", + "de": "Diese Straßenlaterne verwendet Glühlampenlicht" } }, { "if": "light:method=halogen", "then": { "en": "This lamp uses halogen lighting", - "nl": "Deze lantaarn gebruikt halogeen verlichting" + "nl": "Deze lantaarn gebruikt halogeen verlichting", + "de": "Diese Straßenlaterne verwendet Halogenlicht" } }, { "if": "light:method=discharge", "then": { "en": "This lamp uses discharge lamps (unknown type)", - "nl": "Deze lantaarn gebruikt gasontladingslampen (onbekend type)" + "nl": "Deze lantaarn gebruikt gasontladingslampen (onbekend type)", + "de": "Diese Straßenlaterne verwendet Entladungslampen (unbekannter Typ)" } }, { "if": "light:method=mercury", "then": { "en": "This lamp uses a mercury-vapour lamp (lightly blueish)", - "nl": "Deze lantaarn gebruikt een kwiklamp (enigszins blauwachtig)" + "nl": "Deze lantaarn gebruikt een kwiklamp (enigszins blauwachtig)", + "de": "Diese Straßenlaterne verwendet eine Quecksilberdampflampe (leicht bläulich)" } }, { "if": "light:method=metal-halide", "then": { "en": "This lamp uses metal-halide lamps (bright white)", - "nl": "Deze lantaarn gebruikt metaalhalidelampen" + "nl": "Deze lantaarn gebruikt metaalhalidelampen", + "de": "Diese Straßenlaterne verwendet Halogen-Metalldampflampen (hellweiß)" } }, { "if": "light:method=fluorescent", "then": { "en": "This lamp uses fluorescent lighting", - "nl": "Deze lantaarn gebruikt fluorescentieverlichting (TL en spaarlamp)" + "nl": "Deze lantaarn gebruikt fluorescentieverlichting (TL en spaarlamp)", + "de": "Diese Straßenlaterne verwendet Leuchtstoffröhren" } }, { "if": "light:method=sodium", "then": { "en": "This lamp uses sodium lamps (unknown type)", - "nl": "Deze lantaarn gebruikt natriumlampen (onbekend type)" + "nl": "Deze lantaarn gebruikt natriumlampen (onbekend type)", + "de": "Diese Straßenlaterne verwendet Natriumdampflampen (unbekannter Typ)" } }, { "if": "light:method=low_pressure_sodium", "then": { "en": "This lamp uses low pressure sodium lamps (monochrome orange)", - "nl": "Deze lantaarn gebruikt lagedruknatriumlampen (monochroom oranje)" + "nl": "Deze lantaarn gebruikt lagedruknatriumlampen (monochroom oranje)", + "de": "Diese Straßenlaterne verwendet Niederdruck-Natriumdampflampen (einfarbig orange)" } }, { "if": "light:method=high_pressure_sodium", "then": { "en": "This lamp uses high pressure sodium lamps (orange with white)", - "nl": "Deze lantaarn gebruikt hogedruknatriumlampen (oranje met wit)" + "nl": "Deze lantaarn gebruikt hogedruknatriumlampen (oranje met wit)", + "de": "Diese Straßenlaterne verwendet Hochdruck-Natriumdampflampen (orange mit weiß)" } }, { "if": "light:method=gas", "then": { "en": "This lamp is lit using gas", - "nl": "Deze lantaarn wordt verlicht met gas" + "nl": "Deze lantaarn wordt verlicht met gas", + "de": "Diese Straßenlaterne wird mit Gas beleuchtet" } } ] @@ -247,11 +276,13 @@ "id": "colour", "question": { "en": "What colour light does this lamp emit?", - "nl": "Wat voor kleur licht geeft deze lantaarn?" + "nl": "Wat voor kleur licht geeft deze lantaarn?", + "de": "Welche Lichtfarbe strahlt diese Lampe aus?" }, "render": { "en": "This lamp emits {light:colour} light", - "nl": "Deze lantaarn geeft {light:colour} licht" + "nl": "Deze lantaarn geeft {light:colour} licht", + "de": "Diese Lampe strahlt {light:colour} Licht aus" }, "freeform": { "key": "light:colour", @@ -262,21 +293,24 @@ "if": "light:colour=white", "then": { "en": "This lamp emits white light", - "nl": "Deze lantaarn geeft wit licht" + "nl": "Deze lantaarn geeft wit licht", + "de": "Diese Lampe strahlt weißes Licht aus" } }, { "if": "light:colour=green", "then": { "en": "This lamp emits green light", - "nl": "Deze lantaarn geeft groen licht" + "nl": "Deze lantaarn geeft groen licht", + "de": "Diese Lampe strahlt grünes Licht aus" } }, { "if": "light:colour=orange", "then": { "en": "This lamp emits orange light", - "nl": "Deze lantaarn geeft oranje licht" + "nl": "Deze lantaarn geeft oranje licht", + "de": "Diese Lampe strahlt orangefarbenes Licht aus" } } ] @@ -285,11 +319,13 @@ "id": "count", "render": { "en": "This lamp has {light:count} fixtures", - "nl": "Deze lantaarn heeft {light:count} lampen" + "nl": "Deze lantaarn heeft {light:count} lampen", + "de": "Diese Straßenlaterne hat {light:count} Leuchten" }, "question": { "en": "How many fixtures does this light have?", - "nl": "Hoeveel lampen heeft deze lantaarn?" + "nl": "Hoeveel lampen heeft deze lantaarn?", + "de": "Wie viele Leuchten hat diese Straßenlaterne?" }, "condition": "support=pole", "freeform": { @@ -301,14 +337,16 @@ "if": "light:count=1", "then": { "en": "This lamp has 1 fixture", - "nl": "Deze lantaarn heeft 1 lamp" + "nl": "Deze lantaarn heeft 1 lamp", + "de": "Diese Straßenlaterne hat 1 Leuchte" } }, { "if": "light:count=2", "then": { "en": "This lamp has 2 fixtures", - "nl": "Deze lantaarn heeft 2 lampen" + "nl": "Deze lantaarn heeft 2 lampen", + "de": "Diese Straßenlaterne hat 2 Leuchten" } } ] @@ -317,35 +355,40 @@ "id": "lit", "question": { "en": "When is this lamp lit?", - "nl": "Wanneer is deze lantaarn verlicht?" + "nl": "Wanneer is deze lantaarn verlicht?", + "de": "Wann leuchtet diese Straßenlaterne?" }, "mappings": [ { "if": "light:lit=dusk-dawn", "then": { "en": "This lamp is lit at night", - "nl": "Deze lantaarn is 's nachts verlicht" + "nl": "Deze lantaarn is 's nachts verlicht", + "de": "Diese Straßenlaterne leuchtet nachts" } }, { "if": "light:lit=24/7", "then": { "en": "This lamp is lit 24/7", - "nl": "Deze lantaarn is 24/7 verlicht" + "nl": "Deze lantaarn is 24/7 verlicht", + "de": "Diese Straßenlaterne leuchtet durchgehend" } }, { "if": "light:lit=motion", "then": { "en": "This lamp is lit based on motion", - "nl": "Deze lantaarn is verlicht op basis van beweging" + "nl": "Deze lantaarn is verlicht op basis van beweging", + "de": "Diese Straßenlaterne leuchtet bewegungsgesteuert" } }, { "if": "light:lit=demand", "then": { "en": "This lamp is lit based on demand (e.g. with a pushbutton)", - "nl": "Deze lantaarn is verlicht op verzoek (bijv. met een drukknop)" + "nl": "Deze lantaarn is verlicht op verzoek (bijv. met een drukknop)", + "de": "Diese Straßenlaterne leuchtet bei Bedarf (z. B. mit einem Taster)" } } ] @@ -354,11 +397,13 @@ "id": "direction", "render": { "en": "This lamp points towards {light:direction}", - "nl": "Deze lantaarn is gericht naar {light:direction}" + "nl": "Deze lantaarn is gericht naar {light:direction}", + "de": "Diese Straßenlaterne leuchtet in Richtung {light:direction}" }, "question": { "en": "Where does this lamp point to?", - "nl": "Waar is deze lamp heengericht?" + "nl": "Waar is deze lamp heengericht?", + "de": "Wohin leuchtet diese Straßenlaterne?" }, "condition": "light:count=1", "freeform": { @@ -374,6 +419,7 @@ }, "description": { "en": "A layer showing street lights", - "nl": "Een laag die alle straatlantaarns toont" + "nl": "Een laag die alle straatlantaarns toont", + "de": "Eine Ebene mit Straßenbeleuchtung" } } \ No newline at end of file diff --git a/assets/layers/surveillance_camera/surveillance_camera.json b/assets/layers/surveillance_camera/surveillance_camera.json index 271247550..a1e789544 100644 --- a/assets/layers/surveillance_camera/surveillance_camera.json +++ b/assets/layers/surveillance_camera/surveillance_camera.json @@ -6,7 +6,8 @@ "ru": "Камеры наблюдения", "fr": "Caméras de surveillance", "it": "Videocamere di sorveglianza", - "de": "Überwachungskameras" + "de": "Überwachungskameras", + "ca": "Càmeres de videovigilància" }, "minzoom": 12, "source": { @@ -30,7 +31,8 @@ "ru": "Камера наблюдения", "fr": "Caméra de surveillance", "it": "Videocamera di sorveglianza", - "de": "Überwachungskamera" + "de": "Überwachungskamera", + "ca": "Càmera de videovigilància" } }, "tagRenderings": [ @@ -104,7 +106,8 @@ "en": "Films to a compass heading of {camera:direction}", "nl": "Filmt in kompasrichting {camera:direction}", "fr": "Filme dans une direction {camera:direction}", - "it": "Punta in direzione {camera:direction}" + "it": "Punta in direzione {camera:direction}", + "de": "filmt in Himmelsrichtung {camera:direction}" }, "condition": { "or": [ @@ -135,7 +138,8 @@ "en": "Films to a compass heading of {direction}", "nl": "Filmt in kompasrichting {direction}", "fr": "Filme dans une direction {direction}", - "it": "Punta in direzione {direction}" + "it": "Punta in direzione {direction}", + "de": "filmt in Himmelsrichtung {direction}" }, "hideInAnswer": true } @@ -305,11 +309,11 @@ "key": "surveillance:zone" }, "render": { - "en": " Surveills a {surveillance:zone}", + "en": "Surveills a {surveillance:zone}", "nl": "Bewaakt een {surveillance:zone}", - "fr": " Surveille un(e) {surveillance:zone}", + "fr": "Surveille un(e) {surveillance:zone}", "it": " Sorveglia una {surveillance:zone}", - "de": " Überwacht ein/e {surveillance:zone}" + "de": "Überwacht ein/e {surveillance:zone}" }, "mappings": [ { @@ -461,7 +465,8 @@ ], "title": { "en": "a surveillance camera", - "nl": "een bewakingscamera" + "nl": "een bewakingscamera", + "de": "eine Überwachungskamera" } }, { @@ -472,7 +477,8 @@ ], "title": { "en": "a surveillance camera mounted on a wall", - "nl": "een bewakingscamera gemonteerd op een muur" + "nl": "een bewakingscamera gemonteerd op een muur", + "de": "eine an einer Wand montierte Überwachungskamera" }, "preciseInput": { "snapToLayer": "walls_and_buildings" @@ -541,6 +547,7 @@ ], "description": { "en": "This layer shows surveillance cameras and allows a contributor to update information and add new cameras", - "nl": "Deze laag toont bewakingscamera's en laat toe om de informatie te verrijken en om nieuwe camera\"s toe te voegen" + "nl": "Deze laag toont bewakingscamera's en laat toe om de informatie te verrijken en om nieuwe camera\"s toe te voegen", + "de": "Diese Ebene zeigt die Überwachungskameras an und ermöglicht es, Informationen zu aktualisieren und neue Kameras hinzuzufügen" } } \ No newline at end of file diff --git a/assets/layers/toilet/toilet.json b/assets/layers/toilet/toilet.json index 7e2456f39..c485e06c6 100644 --- a/assets/layers/toilet/toilet.json +++ b/assets/layers/toilet/toilet.json @@ -6,7 +6,8 @@ "fr": "Toilettes", "nl": "Toiletten", "ru": "Туалеты", - "it": "Servizi igienici" + "it": "Servizi igienici", + "ca": "Lavabos" }, "minzoom": 12, "source": { @@ -19,7 +20,8 @@ "fr": "Toilettes", "nl": "Toilet", "ru": "Туалет", - "it": "Servizi igienici" + "it": "Servizi igienici", + "ca": "Lavabo" } }, "presets": [ @@ -207,7 +209,8 @@ "id": "Opening-hours", "question": { "en": "When are these toilets opened?", - "nl": "Wanneer zijn deze toiletten open?" + "nl": "Wanneer zijn deze toiletten open?", + "de": "Wann sind diese Toiletten geöffnet?" }, "render": "{opening_hours_table()}", "freeform": { @@ -219,7 +222,8 @@ "if": "opening_hours=24/7", "then": { "en": "Opened 24/7", - "nl": "Altijd open" + "nl": "Altijd open", + "de": "Durchgehend geöffnet" } } ] @@ -443,7 +447,8 @@ "if": "toilets:paper_supplied=yes", "then": { "en": "This toilet is equipped with toilet paper", - "nl": "Deze toilet is voorzien van toiletpapier" + "nl": "Deze toilet is voorzien van toiletpapier", + "de": "Diese Toilette ist mit Toilettenpapier ausgestattet" } }, { @@ -577,6 +582,7 @@ ], "description": { "en": "A layer showing (public) toilets", - "nl": "Een laag die publieke toiletten toont" + "nl": "Een laag die publieke toiletten toont", + "de": "Eine Ebene mit (öffentlichen) Toiletten" } } \ No newline at end of file diff --git a/assets/layers/trail/trail.json b/assets/layers/trail/trail.json index 0ec5f307b..f274c6fa7 100644 --- a/assets/layers/trail/trail.json +++ b/assets/layers/trail/trail.json @@ -5,7 +5,8 @@ "nl": "Wandeltochten", "ru": "Тропы", "de": "Wanderwege", - "fr": "Sentiers" + "fr": "Sentiers", + "ca": "Camins" }, "minzoom": 12, "source": { @@ -28,7 +29,8 @@ "nl": "Wandeltocht", "ru": "Тропа", "de": "Wanderweg", - "fr": "Sentier" + "fr": "Sentier", + "ca": "Camí" }, "mappings": [ { diff --git a/assets/layers/tree_node/tree_node.json b/assets/layers/tree_node/tree_node.json index 72779f6fd..0931dde3f 100644 --- a/assets/layers/tree_node/tree_node.json +++ b/assets/layers/tree_node/tree_node.json @@ -6,7 +6,9 @@ "it": "Albero", "ru": "Дерево", "fr": "Arbre", - "de": "Bäume" + "de": "Bäume", + "ca": "Arbre", + "es": "Árbol" }, "minzoom": 16, "source": { @@ -24,13 +26,37 @@ "ru": "Дерево", "fr": "Arbre", "de": "Baum", - "eo": "Arbo" + "eo": "Arbo", + "ca": "Arbre", + "es": "Árbol" }, "mappings": [ { - "if": "name~*", + "if": { + "and": ["name~*","species:wikidata~*"] + }, "then": { - "*": "{name}" + "*": "{name} ({wikidata_label(species:wikidata)})" + } + }, + { + "if": { + "and": ["name~*"] + }, + "then": { + "*": "{name}" + } + }, + { + "if": "species:wikidata~*", + "then": { + "*": "{wikidata_label(species:wikidata)}" + } + }, + { + "if": "species~*", + "then": { + "*": "{species}" } } ] @@ -45,7 +71,8 @@ "it": "Altezza: {height}", "ru": "Высота: {height}", "fr": "Hauteur : {height}", - "de": "Höhe: {height}" + "de": "Höhe: {height}", + "es": "Altura: {height}" }, "condition": { "and": [ @@ -65,7 +92,8 @@ "it": "Altezza: {height} m", "ru": "Высота: {height} м", "fr": "Hauteur : {height} m", - "de": "Höhe: {height} m" + "de": "Höhe: {height} m", + "es": "Altura: {height} m" } } ] @@ -77,7 +105,8 @@ "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 ?", - "de": "Ist dies ein Laub- oder Nadelbaum?" + "de": "Ist dies ein Laub- oder Nadelbaum?", + "es": "¿Es un árbol de hoja ancha o de hoja aguja?" }, "mappings": [ { @@ -91,7 +120,9 @@ "en": "Broadleaved", "it": "Latifoglia", "fr": "Feuillu", - "de": "Laubbaum" + "de": "Laubbaum", + "ca": "De fulla ampla", + "es": "Latifoliada" }, "icon": { "path": "./assets/themes/trees/broadleaved.svg", @@ -109,7 +140,9 @@ "en": "Needleleaved", "it": "Aghifoglia", "fr": "Résineux", - "de": "Nadelbaum" + "de": "Nadelbaum", + "ca": "Amb fulles d'agulla", + "es": "Hoja aguja" }, "icon": { "path": "./assets/themes/trees/needleleaved.svg", @@ -127,7 +160,8 @@ "en": "Permanently leafless", "it": "Privo di foglie (permanente)", "fr": "Sans feuilles (Permanent)", - "de": "Dauerhaft blattlos" + "de": "Dauerhaft blattlos", + "es": "Permanentemente sin hojas" }, "hideInAnswer": true, "icon": { @@ -144,7 +178,8 @@ "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.", - "de": "Wie bedeutsam ist dieser Baum? Wählen Sie die erste Antwort, die zutrifft." + "de": "Wie bedeutsam ist dieser Baum? Wählen Sie die erste Antwort, die zutrifft.", + "es": "¿Qué importancia tiene este árbol? Elige la primera respuesta que corresponda." }, "mappings": [ { @@ -158,7 +193,8 @@ "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.", - "de": "Der Baum ist aufgrund seiner Größe oder seiner markanten Lage bedeutsam. Er ist nützlich zur Orientierung." + "de": "Der Baum ist aufgrund seiner Größe oder seiner markanten Lage bedeutsam. Er ist nützlich zur Orientierung.", + "es": "El árbol es notable debido a su tamaño o ubicación prominente. Es útil para la navegación." } }, { @@ -172,7 +208,8 @@ "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…)", - "de": "Der Baum ist ein Naturdenkmal, z. B. weil er besonders alt ist oder zu einer wertvollen Art gehört." + "de": "Der Baum ist ein Naturdenkmal, z. B. weil er besonders alt ist oder zu einer wertvollen Art gehört.", + "es": "El árbol es un monumento natural, por ejemplo, porque es especialmente antiguo, o de una especie valiosa." } }, { @@ -186,7 +223,8 @@ "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)", - "de": "Der Baum wird für landwirtschaftliche Zwecke genutzt, z. B. in einer Obstplantage." + "de": "Der Baum wird für landwirtschaftliche Zwecke genutzt, z. B. in einer Obstplantage.", + "es": "El árbol se utiliza con fines agrícolas, por ejemplo, en un huerto." } }, { @@ -200,7 +238,8 @@ "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, …).", - "de": "Der Baum steht in einem Park oder ähnlichem (Friedhof, Schulgelände, ...)." + "de": "Der Baum steht in einem Park oder ähnlichem (Friedhof, Schulgelände, ...).", + "es": "El árbol está en un parque o similar (cementerio, recinto escolar, ...)." } }, { @@ -213,7 +252,9 @@ "nl": "De boom staat in de tuin bij een woning/flatgebouw.", "en": "The tree is a residential garden.", "it": "L’albero è un giardino residenziale.", - "fr": "Cet arbre est dans une cour résidentielle." + "fr": "Cet arbre est dans une cour résidentielle.", + "es": "El árbol está en un jardín privado o residencial.", + "de": "Der Baum steht in einem Wohngarten." } }, { @@ -227,7 +268,8 @@ "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.", - "de": "Dieser Baum steht entlang einer Straße." + "de": "Dieser Baum steht entlang einer Straße.", + "es": "El árbol está en bandejón de una avenida." } }, { @@ -240,7 +282,9 @@ "nl": "De boom staat in een woonkern.", "en": "The tree is an urban area.", "it": "L’albero si trova in un’area urbana.", - "fr": "L'arbre est une zone urbaine." + "fr": "L'arbre est une zone urbaine.", + "es": "El árbol está en un zona urbana.", + "de": "Der Baum steht in einem städtischen Gebiet." } }, { @@ -254,7 +298,8 @@ "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.", - "de": "Dieser Baum steht außerhalb eines städtischen Gebiets." + "de": "Dieser Baum steht außerhalb eines städtischen Gebiets.", + "es": "El árbol está fuera de una zona urbana." } } ] @@ -267,7 +312,8 @@ "it": "È un sempreverde o caduco?", "ru": "Это дерево вечнозелёное или листопадное?", "fr": "L’arbre est-il à feuillage persistant ou caduc ?", - "de": "Ist dies ein Nadelbaum oder ein Laubbaum?" + "de": "Ist dies ein Nadelbaum oder ein Laubbaum?", + "es": "¿El árbol es Siempreverde o Caduco?" }, "mappings": [ { @@ -282,7 +328,8 @@ "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.", - "de": "Laubabwerfend: Der Baum verliert für eine gewisse Zeit des Jahres seine Blätter." + "de": "Laubabwerfend: Der Baum verliert für eine gewisse Zeit des Jahres seine Blätter.", + "es": "Caduco o Deciduo: el árbol pierde las hojas en un período del año" } }, { @@ -297,7 +344,9 @@ "it": "Sempreverde.", "fr": "À feuilles persistantes.", "ru": "Вечнозелёное.", - "de": "immergrüner Baum." + "de": "immergrüner Baum.", + "ca": "Perenne.", + "es": "Siempreverde." } } ], @@ -307,6 +356,41 @@ ] } }, + { + "id": "tree-species-wikidata", + "question": { + "en": "What species is this tree?" + }, + "render": { + "*": "{wikipedia(species:wikidata):max-height: 25rem}" + }, + "freeform": { + "key": "species:wikidata", + "type": "wikidata", + "helperArgs": [ + "species", + { + "instanceOf": [ + 10884, + 16521 + ] + } + ] + } + }, + { + "id": "tree-wikipedia", + "#": "If this tree has a wikipedia article, show it. People can _only_ set the species though!", + "render": { + "*": "{wikipedia()}" + }, + "condition": { + "or": [ + "wikipedia~*", + "wikidata~*" + ] + } + }, { "render": { "nl": "Naam: {name}", @@ -324,7 +408,8 @@ "it": "L’albero ha un nome?", "fr": "L'arbre a-t-il un nom ?", "ru": "Есть ли у этого дерева название?", - "de": "Hat der Baum einen Namen?" + "de": "Hat der Baum einen Namen?", + "es": "El árbol no tiene nombre?." }, "freeform": { "key": "name", @@ -346,7 +431,8 @@ "it": "L’albero non ha un nome.", "fr": "L'arbre n'a pas de nom.", "ru": "У этого дерева нет названия.", - "de": "Der Baum hat keinen Namen." + "de": "Der Baum hat keinen Namen.", + "es": "No identificas la especie." } } ], @@ -366,7 +452,8 @@ "en": "Is this tree registered heritage?", "it": "Quest’albero è registrato come patrimonio?", "fr": "Cet arbre est-il inscrit au patrimoine ?", - "de": "Ist dieser Baum ein Naturdenkmal?" + "de": "Ist dieser Baum ein Naturdenkmal?", + "es": "¿Este árbol es patrimonio registrado?" }, "mappings": [ { @@ -381,7 +468,8 @@ "en": "Registered as heritage by Onroerend Erfgoed Flanders", "it": "Registrato come patrimonio da Onroerend Erfgoed Flanders", "fr": "Fait partie du patrimoine par Onroerend Erfgoed", - "de": "Als Denkmal registriert von der Onroerend Erfgoed Flandern" + "de": "Als Denkmal registriert von der Onroerend Erfgoed Flandern", + "es": "Registrado como patrimonio por Onroerend Erfgoed Flandes" }, "icon": { "path": "./assets/layers/tree_node/Onroerend_Erfgoed_logo_without_text.svg", @@ -400,7 +488,8 @@ "en": "Registered as heritage by Direction du Patrimoine culturel Brussels", "it": "Registrato come patrimonio da Direction du Patrimoine culturel di Bruxelles", "fr": "Enregistré comme patrimoine par la Direction du Patrimoine culturel Bruxelles", - "de": "Als Denkmal registriert von der Direction du Patrimoine culturel Brüssel" + "de": "Als Denkmal registriert von der Direction du Patrimoine culturel Brüssel", + "es": "Registrado como patrimonio por la Dirección de Patrimonio Cultural de Bruselas" } }, { @@ -415,7 +504,8 @@ "en": "Registered as heritage by a different organisation", "it": "Registrato come patrimonio da un’organizzazione differente", "fr": "Enregistré comme patrimoine par une autre organisation", - "de": "Von einer anderen Organisation als Denkmal registriert" + "de": "Von einer anderen Organisation als Denkmal registriert", + "es": "Registrado como patrimonio por una organización diferente" } }, { @@ -430,7 +520,8 @@ "en": "Not registered as heritage", "it": "Non è registrato come patrimonio", "fr": "Non enregistré comme patrimoine", - "de": "Nicht als Denkmal registriert" + "de": "Nicht als Denkmal registriert", + "es": "No registrado como patrimonio" } }, { @@ -444,7 +535,8 @@ "en": "Registered as heritage by a different organisation", "it": "Registrato come patrimonio da un’organizzazione differente", "fr": "Enregistré comme patrimoine par une autre organisation", - "de": "Von einer anderen Organisation als Denkmal registriert" + "de": "Von einer anderen Organisation als Denkmal registriert", + "es": "Registrado como patrimonio por un organización diferente" }, "hideInAnswer": true } @@ -462,14 +554,16 @@ "en": "\"\"/ Onroerend Erfgoed ID: {ref:OnroerendErfgoed}", "it": "\"\"/ Onroerend Erfgoed ID: {ref:OnroerendErfgoed}", "ru": "\"\"/ Onroerend Erfgoed ID: {ref:OnroerendErfgoed}", - "fr": "\"\"/ Identifiant Onroerend Erfgoed : {ref:OnroerendErfgoed}" + "fr": "\"\"/ Identifiant Onroerend Erfgoed : {ref:OnroerendErfgoed}", + "de": "\"\"/ Onroerend Erfgoed Kennung: {ref:OnroerendErfgoed}" }, "question": { "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 ?", - "de": "Wie lautet die Kennung der Onroerend Erfgoed Flanders?" + "de": "Wie lautet die Kennung der Onroerend Erfgoed Flanders?", + "es": "¿Cuál es la identificación emitida por Onroerend Erfgoed Flandes?" }, "freeform": { "key": "ref:OnroerendErfgoed", @@ -490,14 +584,16 @@ "it": "\"\"/ Wikidata: {wikidata}", "ru": "\"\"/ Wikidata: {wikidata}", "fr": "\"\"/ Wikidata : {wikidata}", - "de": "\"\"/ Wikidata: {wikidata}" + "de": "\"\"/ Wikidata: {wikidata}", + "es": "\"\"/ Wikidata: {wikidata}" }, "question": { "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 ?", - "de": "Was ist das passende Wikidata Element zu diesem Baum?" + "de": "Was ist das passende Wikidata Element zu diesem Baum?", + "es": "¿Cuál es el ID de Wikidata para este árbol?" }, "freeform": { "key": "wikidata", @@ -525,14 +621,16 @@ "it": "una albero latifoglia", "fr": "une arbre feuillu", "ru": "Лиственное дерево", - "de": "eine laubbaum" + "de": "eine laubbaum", + "es": "árbol de hoja ancha" }, "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.", - "de": "Ein Baum mit Blättern, z. B. Eiche oder Buche." + "de": "Ein Baum mit Blättern, z. B. Eiche oder Buche.", + "es": "Un árbol de hojas como el Roble o el Álamo." }, "preciseInput": { "preferredBackground": "photo" @@ -549,7 +647,8 @@ "it": "una albero aghifoglia", "ru": "Хвойное дерево", "fr": "une arbre résineux", - "de": "eine nadelbaum" + "de": "eine nadelbaum", + "es": "Árbol tipo Conífera" }, "description": { "nl": "Een boom van een soort met naalden, bijvoorbeeld den of spar.", @@ -557,7 +656,8 @@ "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.", - "de": "Ein Baum mit Nadeln, z. B. Kiefer oder Fichte." + "de": "Ein Baum mit Nadeln, z. B. Kiefer oder Fichte.", + "es": "Un árbol de hojas agujas, como el Pino o el Abeto." }, "preciseInput": { "preferredBackground": "photo" @@ -574,7 +674,9 @@ "ru": "Дерево", "fr": "une arbre", "id": "Pohon", - "de": "eine baum" + "de": "eine baum", + "ca": "un arbre", + "es": "un árbol" }, "description": { "nl": "Wanneer je niet zeker bent of het nu een loof- of naaldboom is.", @@ -582,7 +684,8 @@ "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": "Если вы не уверены в том, лиственное это дерево или хвойное.", - "de": "Wenn Sie nicht sicher sind, ob es sich um einen Laubbaum oder einen Nadelbaum handelt." + "de": "Wenn Sie nicht sicher sind, ob es sich um einen Laubbaum oder einen Nadelbaum handelt.", + "es": "Si no estás seguro de si es un árbol de hoja ancha o de hoja de aguja." }, "preciseInput": { "preferredBackground": "photo" @@ -630,6 +733,8 @@ ], "description": { "en": "A layer showing trees", - "nl": "Een laag die bomen toont" + "nl": "Een laag die bomen toont", + "es": "Una capa que muestra árboles", + "de": "Eine Ebene, die Bäume zeigt" } } \ No newline at end of file diff --git a/assets/layers/viewpoint/viewpoint.json b/assets/layers/viewpoint/viewpoint.json index 654157082..70f743b50 100644 --- a/assets/layers/viewpoint/viewpoint.json +++ b/assets/layers/viewpoint/viewpoint.json @@ -8,7 +8,8 @@ "it": "Punto panoramico", "ru": "Смотровая площадка", "id": "Sudut pandang", - "eo": "Vidpunkto" + "eo": "Vidpunkto", + "ca": "Mirador" }, "description": { "en": "A nice viewpoint or nice view. Ideal to add an image if no other category fits", @@ -31,7 +32,8 @@ "fr": "une point de vue", "ru": "Смотровая площадка", "it": "una punto panoramico", - "id": "Sudut pandang" + "id": "Sudut pandang", + "ca": "un mirador" }, "tags": [ "tourism=viewpoint" @@ -47,7 +49,8 @@ "ru": "Смотровая площадка", "it": "Punto panoramico", "id": "Sudut pandang", - "eo": "Vidpunkto" + "eo": "Vidpunkto", + "ca": "Mirador" } }, "tagRenderings": [ diff --git a/assets/layers/village_green/village_green.json b/assets/layers/village_green/village_green.json index 1cbd49f40..b5d095f3e 100644 --- a/assets/layers/village_green/village_green.json +++ b/assets/layers/village_green/village_green.json @@ -47,6 +47,7 @@ ], "description": { "en": "A layer showing village-green (which are communal green areas, but not quite parks)", - "nl": "Een laag die dorpsgroen toont (gemeenschapsgroen, maar niet echt een park)" + "nl": "Een laag die dorpsgroen toont (gemeenschapsgroen, maar niet echt een park)", + "de": "Eine Ebene mit Dorfangern (kommunale Grünflächen, aber nicht wirklich Parks)" } } \ No newline at end of file diff --git a/assets/layers/visitor_information_centre/visitor_information_centre.json b/assets/layers/visitor_information_centre/visitor_information_centre.json index 499c6e1a7..16ad90e35 100644 --- a/assets/layers/visitor_information_centre/visitor_information_centre.json +++ b/assets/layers/visitor_information_centre/visitor_information_centre.json @@ -25,7 +25,8 @@ "de": "{name}", "ru": "{name}", "eo": "{name}", - "fr": "{name}" + "fr": "{name}", + "ca": "{name}" }, "mappings": [ { @@ -50,7 +51,8 @@ "de": "{name}", "ru": "{name}", "eo": "{name}", - "fr": "{name}" + "fr": "{name}", + "ca": "{name}" } } ] diff --git a/assets/layers/walls_and_buildings/walls_and_buildings.json b/assets/layers/walls_and_buildings/walls_and_buildings.json index cb71301cf..48638c38d 100644 --- a/assets/layers/walls_and_buildings/walls_and_buildings.json +++ b/assets/layers/walls_and_buildings/walls_and_buildings.json @@ -4,12 +4,14 @@ "title": { "render": { "en": "Wall or building", - "nl": "Muur of gebouw" + "nl": "Muur of gebouw", + "de": "Wand oder Gebäude" } }, "description": { "en": "Special builtin layer providing all walls and buildings. This layer is useful in presets for objects which can be placed against walls (e.g. AEDs, postboxes, entrances, addresses, surveillance cameras, ...). This layer is invisible by default and not toggleable by the user.", - "nl": "Speciale laag met alle muren en gebouwen. Deze laag is nuttig om objecten toe te voegen die met een muur verbonden zijn (zoals AEDs, brievenbussen, adressen, bewakingscamera's,...). Deze laag is standaard onzichtbaar en kan niet aangezet worden door de gebruiker." + "nl": "Speciale laag met alle muren en gebouwen. Deze laag is nuttig om objecten toe te voegen die met een muur verbonden zijn (zoals AEDs, brievenbussen, adressen, bewakingscamera's,...). Deze laag is standaard onzichtbaar en kan niet aangezet worden door de gebruiker.", + "de": "Spezielle eingebaute Ebene, die alle Wände und Gebäude bereitstellt. Diese Ebene ist in Voreinstellungen für Objekte nützlich, die an Wänden platziert werden können (z. B. AEDs, Briefkästen, Eingänge, Adressen, Überwachungskameras, ...). Diese Ebene ist standardmäßig unsichtbar und kann vom Benutzer nicht umgeschaltet werden." }, "source": { "osmTags": { diff --git a/assets/layers/waste_basket/waste_basket.json b/assets/layers/waste_basket/waste_basket.json index 26165777f..67d968702 100644 --- a/assets/layers/waste_basket/waste_basket.json +++ b/assets/layers/waste_basket/waste_basket.json @@ -5,7 +5,8 @@ "nl": "Vuilnisbak", "ru": "Контейнер для мусора", "de": "Abfalleimer", - "eo": "Rubujo" + "eo": "Rubujo", + "ca": "Paperera" }, "minzoom": 17, "source": { @@ -20,7 +21,8 @@ "en": "Waste Basket", "nl": "Vuilnisbak", "ru": "Контейнер для мусора", - "de": "Abfalleimer" + "de": "Abfalleimer", + "ca": "Paperera" } }, "description": { @@ -29,6 +31,7 @@ "de": "Dies ist ein öffentlicher Abfalleimer, in den Sie Ihren Müll entsorgen können." }, "tagRenderings": [ + "images", { "id": "waste-basket-waste-types", "question": { diff --git a/assets/layers/waste_disposal/waste_disposal.json b/assets/layers/waste_disposal/waste_disposal.json index 9e9322ef1..286f074f6 100644 --- a/assets/layers/waste_disposal/waste_disposal.json +++ b/assets/layers/waste_disposal/waste_disposal.json @@ -2,11 +2,13 @@ "id": "waste_disposal", "name": { "en": "Waste Disposal Bins", - "nl": "Afvalcontainers voor huishoudelijk afval" + "nl": "Afvalcontainers voor huishoudelijk afval", + "de": "Mülleimer" }, "description": { "en": "Waste Disposal Bin, medium to large bin for disposal of (household) waste", - "nl": "Een grote afvalcontainer voor (huishoudelijk) afval" + "nl": "Een grote afvalcontainer voor (huishoudelijk) afval", + "de": "Entsorgungsbehälter, mittlerer bis großer Behälter zur Entsorgung von (Haushalts-)Abfällen" }, "source": { "osmTags": "amenity=waste_disposal" @@ -16,7 +18,8 @@ "title": { "render": { "en": "Waste Disposal", - "nl": "Afvalbak" + "nl": "Afvalbak", + "de": "Abfallentsorgung" } }, "mapRendering": [ @@ -32,14 +35,16 @@ { "title": { "en": "a waste disposal bin", - "nl": "Een afvalcontainer" + "nl": "Een afvalcontainer", + "de": "ein Abfalleimer" }, "tags": [ "amenity=waste_disposal" ], "description": { "en": "Medium to large bin for disposal of (household) waste", - "nl": "middelgrote of grote afvalcontainer voor (huishoudelijk) afval" + "nl": "middelgrote of grote afvalcontainer voor (huishoudelijk) afval", + "de": "Mittlere bis große Mülltonne für die Entsorgung von (Haushalts-)Abfällen" } } ], @@ -48,11 +53,13 @@ "id": "access", "render": { "en": "Access: {access}", - "nl": "Toegankelijk voor {access}" + "nl": "Toegankelijk voor {access}", + "de": "Zugang: {access}" }, "question": { "en": "Who can use this waste disposal bin?", - "nl": "Wie mag deze afvalcontainer gebruiken?" + "nl": "Wie mag deze afvalcontainer gebruiken?", + "de": "Wer kann diese Mülltonne benutzen?" }, "freeform": { "key": "access", @@ -63,21 +70,24 @@ "if": "access=yes", "then": { "en": "This bin can be used by anyone", - "nl": "Iedereen mag deze afvalcontainer gebruiken" + "nl": "Iedereen mag deze afvalcontainer gebruiken", + "de": "Dieser Behälter kann von jedem benutzt werden" } }, { "if": "access=no", "then": { "en": "This bin is private", - "nl": "Deze afvalcontainer is enkel voor privaat gebruik" + "nl": "Deze afvalcontainer is enkel voor privaat gebruik", + "de": "Dieser Behälter ist privat" } }, { "if": "access=residents", "then": { "en": "This bin is only for residents", - "nl": "Enkel bewoners mogen deze afvalcontainer gebruiken" + "nl": "Enkel bewoners mogen deze afvalcontainer gebruiken", + "de": "Diese Mülltonne ist nur für Anwohner" } } ] @@ -86,28 +96,32 @@ "id": "disposal-location", "question": { "en": "Where is this container located?", - "nl": "Waar bevindt deze container zich?" + "nl": "Waar bevindt deze container zich?", + "de": "Wo befindet sich dieser Container?" }, "mappings": [ { "if": "location=underground", "then": { "en": "This is an underground container", - "nl": "Dit is een ondergrondse container" + "nl": "Dit is een ondergrondse container", + "de": "Dies ist ein unterirdischer Container" } }, { "if": "location=indoor", "then": { "en": "This container is located indoors", - "nl": "Deze container bevindt zich binnen" + "nl": "Deze container bevindt zich binnen", + "de": "Dieser Container befindet sich in einem Gebäude" } }, { "if": "location=", "then": { "en": "This container is located outdoors", - "nl": "Deze container is buiten" + "nl": "Deze container is buiten", + "de": "Dieser Container befindet sich im Freien" } } ] @@ -120,7 +134,8 @@ { "question": { "en": "Only public access", - "nl": "Enkel publiek toegankelijke afvalcontainers" + "nl": "Enkel publiek toegankelijke afvalcontainers", + "de": "Nur öffentlich zugänglich" }, "osmTags": "access=yes" } diff --git a/assets/layers/watermill/watermill.json b/assets/layers/watermill/watermill.json index b69a4d4de..7da024722 100644 --- a/assets/layers/watermill/watermill.json +++ b/assets/layers/watermill/watermill.json @@ -6,7 +6,8 @@ "de": "Wassermühle", "ru": "Водяная мельница", "id": "Kincir Air", - "fr": "Moulin à eau" + "fr": "Moulin à eau", + "ca": "Molí d'aigua" }, "minzoom": 12, "source": { diff --git a/assets/layers/windturbine/windturbine.json b/assets/layers/windturbine/windturbine.json new file mode 100644 index 000000000..3e51ea7e1 --- /dev/null +++ b/assets/layers/windturbine/windturbine.json @@ -0,0 +1,322 @@ +{ + "id": "windturbine", + "name": { + "en": "wind turbine", + "nl": "windturbine", + "fr": "Éolienne", + "de": "Windräder", + "it": "pala eolica", + "zh_Hant": "風機", + "hu": "Szélerőmű" + }, + "description": { + "en": "Modern windmills generating electricity" + }, + "source": { + "osmTags": "generator:source=wind" + }, + "minzoom": 10, + "title": { + "render": { + "en": "wind turbine", + "nl": "windturbine", + "fr": "éolienne", + "de": "Windrad", + "it": "pala eolica", + "zh_Hant": "風機", + "id": "turbin angin", + "hu": "szélerőmű" + }, + "mappings": [ + { + "if": "name~*", + "then": { + "en": "{name}", + "fr": "{name}", + "eo": "{name}", + "it": "{name}", + "ru": "{name}", + "zh_Hant": "{name}", + "id": "{name}", + "de": "{name}", + "ca": "{name}" + } + } + ] + }, + "tagRenderings": [ + { + "id": "turbine-output", + "render": { + "en": "The power output of this wind turbine is {generator:output:electricity}.", + "fr": "La puissance générée par cette éolienne est de {generator:output:electricity}.", + "it": "La potenza generata da questa pala eolica è {generator:output:electricity}.", + "zh_Hant": "這個風機的電力輸出是 {generator:output:electricity}。", + "id": "Output daya dari turbin angin ini adalah {generator:output:electricity}.", + "hu": "A szélerőmű teljesítménye: {generator:output:electricity}.", + "de": "Das Windrad erzeugt {generator:output:electricity} Strom." + }, + "question": { + "en": "What is the power output of this wind turbine? (e.g. 2.3 MW)", + "fr": "Quel est la puissance générée par cette éolienne ?", + "it": "Quant’è la potenza generata da questa pala eolica? (ad es. 2.3 MW)", + "zh_Hant": "這個風機的電力輸出是多少?(例如 2.3 MW)", + "id": "Berapa output daya dari turbin angin ini? (misalnya 2,3 MW)", + "hu": "Mekkora a teljesítménye ennek a szélturbinának? (pl. 2.3 MW)", + "de": "Wieviel Strom erzeugt das Windrad? (z.B. 2.3MW)" + }, + "freeform": { + "key": "generator:output:electricity", + "type": "pfloat" + } + }, + { + "id": "turbine-operator", + "render": { + "en": "This wind turbine is operated by {operator}.", + "fr": "Cette éolienne est opérée par {operator}.", + "it": "Questa pala eolica è gestita da {operator}.", + "zh_Hant": "這個風機營業商是 {operator}。", + "id": "Turbin angin ini dioperasikan oleh {operator}.", + "hu": "Ennek a szélerőműnek az üzemeltetője: {operator}.", + "de": "Die Windturbine wird betrieben von {operator}." + }, + "question": { + "en": "Who operates this wind turbine?", + "fr": "Qui est l’exploitant de cette éolienne ?", + "it": "Chi gestisce questa pala eolica?", + "zh_Hant": "這個風機營業商是?", + "hu": "Ki üzemelteti ezt a szélturbinát?", + "de": "Wer betreibt das Windrads?" + }, + "freeform": { + "key": "operator" + } + }, + { + "id": "turbine-height", + "render": { + "en": "The total height (including rotor radius) of this wind turbine is {height} metres.", + "fr": "La hauteur totale, incluant les pales, est de {height} mètres.", + "it": "L’altezza totale (raggio del rotore incluso) di questa pala eolica è di {height} metri.", + "zh_Hant": "這風機的總高度 (包括風葉直徑) 是 {height} 公尺。", + "hu": "A szélerőmű teljes (rotor sugarával együtt számított) magassága: {height} méter.", + "de": "Die Gesamthöhe dieses Windrads beträgt (einschließlich Rotorradius) {height} Meter." + }, + "question": { + "en": "What is the total height of this wind turbine (including rotor radius), in metres?", + "fr": "Quelle est la hauteur totale de l’éolienne en mètres, pales incluses ?", + "it": "Qual è l’altezza (in metri e raggio del rotore incluso) di questa pala eolica?", + "zh_Hant": "這個風機的總高度是多少 (包括風葉大小) 公尺?", + "hu": "Hány méter a szélerőmű teljes magassága (a rotor sugarával együtt)?", + "de": "Wie hoch ist dieses Windrad (inklusive Rotorradius) in Metern?" + }, + "freeform": { + "key": "height", + "type": "pfloat" + } + }, + { + "id": "turbine-diameter", + "render": { + "en": "The rotor diameter of this wind turbine is {rotor:diameter} metres.", + "fr": "Le diamètre du rotor est de {rotor:diameter} mètres.", + "it": "Il diametro del rotore di questa pala eolica è di {rotor:diameter} metri.", + "zh_Hant": "這個風力渦輪機的風葉直徑是 {rotor:diameter} 公尺。", + "hu": "A szélturbina rotorátmérője: {rotor:diameter} méter.", + "de": "Der Rotordurchmesser der Windturbine ist {rotor:diameter} Meter." + }, + "question": { + "en": "What is the rotor diameter of this wind turbine, in metres?", + "fr": "Quel est le diamètre du rotor en mètres ?", + "it": "Qual è il diametro (in metri) del rotore di questa pala eolica?", + "zh_Hant": "這個風力渦輪機的風葉直徑是多少公尺?", + "hu": "Hány méter a rotorátmérője ennek a szélturbinának?", + "de": "Wie groß ist der Rotordurchmesser der Windturbine in Meter?" + }, + "freeform": { + "key": "rotor:diameter", + "type": "float" + } + }, + { + "id": "turbine-start-date", + "render": { + "en": "This wind turbine went into operation on/in {start_date}.", + "fr": "L’éolienne est active depuis {start_date}.", + "it": "Questa pala eolica è entrata in funzione in data {start_date}.", + "zh_Hant": "這個風機從 {start_date} 開始運轉。", + "id": "Turbin angin ini mulai beroperasi pada/dalam {start_date}.", + "hu": "A szélerőmű üzembe helyezése: {start_date}.", + "de": "Das Windrad wurde am {start_date} in Betrieb genommen." + }, + "question": { + "en": "When did this wind turbine go into operation?", + "fr": "Depuis quand l’éolienne est-elle en fonctionnement ?", + "it": "Quando è entrata in funzione questa pala eolica?", + "zh_Hant": "這個風機何時開始營運?", + "id": "Kapan turbin angin ini mulai beroperasi?", + "hu": "Mikor helyezték üzembe ezt a szélerőművet?", + "de": "Wann wurde das Windrad in Betrieb genommen?" + }, + "freeform": { + "key": "start_date", + "type": "date" + } + }, + "images" + ], + "presets": [ + { + "tags": [ + "power=generator", + "generator:source=wind" + ], + "title": { + "en": "a wind turbine", + "nl": "een windturbine", + "fr": "une éolienne", + "de": "ein Windrad", + "it": "una pala eolica", + "zh_Hant": "風機", + "hu": "Szélerőmű" + } + } + ], + "units": [ + { + "appliesToKey": [ + "generator:output:electricity" + ], + "applicableUnits": [ + { + "canonicalDenomination": "MW", + "alternativeDenomination": [ + "megawatts", + "megawatt" + ], + "human": { + "en": " megawatts", + "nl": " megawatt", + "fr": " megawatts", + "de": " Megawatt", + "eo": " megavatoj", + "it": " megawatt", + "ru": " мегаватт", + "zh_Hant": " 百萬瓦", + "id": " megawat", + "hu": " megawatt", + "ca": " megavats" + } + }, + { + "canonicalDenomination": "kW", + "alternativeDenomination": [ + "kilowatts", + "kilowatt" + ], + "human": { + "en": " kilowatts", + "nl": " kilowatt", + "fr": " kilowatts", + "de": " Kilowatt", + "eo": " kilovatoj", + "it": " kilowatt", + "nb_NO": " kilowatt", + "ru": " киловатт", + "zh_Hant": " 千瓦", + "id": " kilowat", + "hu": " kilowatt", + "ca": " quilovats" + } + }, + { + "canonicalDenomination": "W", + "alternativeDenomination": [ + "watts", + "watt" + ], + "human": { + "en": " watts", + "nl": " watt", + "fr": " watts", + "de": " Watt", + "eo": " vatoj", + "it": " watt", + "ru": " ватт", + "zh_Hant": " 瓦", + "id": " watt", + "hu": " watt", + "ca": " vats" + } + }, + { + "canonicalDenomination": "GW", + "alternativeDenomination": [ + "gigawatts", + "gigawatt" + ], + "human": { + "en": " gigawatts", + "nl": " gigawatt", + "fr": " gigawatts", + "de": " Gigawatt", + "eo": " gigavatoj", + "it": " gigawatt", + "ru": " гигаватт", + "zh_Hant": " 千兆瓦", + "id": " gigawatt", + "hu": " gigawatt", + "ca": " gigavats" + } + } + ], + "eraseInvalidValues": true + }, + { + "appliesToKey": [ + "height", + "rotor:diameter" + ], + "applicableUnits": [ + { + "canonicalDenomination": "m", + "alternativeDenomination": [ + "meter" + ], + "human": { + "en": " meter", + "nl": " meter", + "fr": " mètres", + "de": " Meter", + "eo": " metro", + "it": " metri", + "ru": " метр", + "zh_Hant": " 公尺", + "id": " meter", + "hu": " méter", + "ca": " metre" + } + } + ] + } + ], + "mapRendering": [ + { + "icon": "./assets/themes/openwindpowermap/wind_turbine.svg", + "label": { + "mappings": [ + { + "if": "generator:output:electricity~^[0-9]+.*[W]$", + "then": "
    {generator:output:electricity}
    " + } + ] + }, + "iconSize": "40, 40, bottom", + "location": [ + "point", + "centroid" + ] + } + ] +} \ No newline at end of file diff --git a/assets/tagRenderings/questions.json b/assets/tagRenderings/questions.json index 3d6049879..55620b18d 100644 --- a/assets/tagRenderings/questions.json +++ b/assets/tagRenderings/questions.json @@ -27,7 +27,10 @@ "sv": "Vad är den motsvarande Wikidata-enheten?", "zh_Hant": "對應的維基資料項目是?", "pl": "Jaki jest powiązany obiekt Wikidata?", - "ja": "対応するウィキデータのエンティティは何ですか?" + "ja": "対応するウィキデータのエンティティは何ですか?", + "fil": "Ano ang nau-ukol na entidad sa Wikidata?", + "es": "¿Cual es la entidad de Wikidata que se corresponde?", + "zh_Hans": "在Wikidata上对应的实体是什么?" }, "mappings": [ { @@ -46,7 +49,10 @@ "zh_Hant": "還沒有連結到維基百科頁面", "ru": "Никакой страницы на Википедии не было прикреплено", "pl": "Link do strony Wikipedii nie został jeszcze określony", - "ja": "ウィキペディアのページはまだリンクされていません" + "ja": "ウィキペディアのページはまだリンクされていません", + "fil": "Wala pang kawing ng Wikipedia page", + "es": "Todavía no se ha enlazado una página de wikipedia", + "zh_Hans": "尚未有连接到的维基百科页面" }, "hideInAnswer": true } @@ -81,7 +87,10 @@ "hu": "Mi a telefonszáma ennek: {title()}?", "ca": "Quin és el telèfon de {title()}?", "ja": "{title()}の電話番号は?", - "sl": "Kakšno telefonsko številko ima {title()}?" + "sl": "Kakšno telefonsko številko ima {title()}?", + "fil": "Ano ang telepono ng {title()}?", + "es": "¿Cuál es el número de teléfono de {title()}?", + "zh_Hans": "{title()} 的电话号码为何?" }, "render": "{phone}", "mappings": [ @@ -123,7 +132,10 @@ "zh_Hant": "維基百科上對應的項目是什麼?", "fr": "Quel est l’élément Wikipédia correspondant ?", "pl": "Jaki jest link do strony Wikipedii?", - "ja": "Wikipediaの該当項目は何ですか?" + "ja": "Wikipediaの該当項目は何ですか?", + "fil": "Ano ang nau-ukol na partida sa Wikipedia?", + "es": "¿Cual es el ítem correspondiente en Wikipedia?", + "zh_Hans": "在维基百科上对应的条目是什么?" }, "mappings": [ { @@ -141,7 +153,10 @@ "sv": "Inte länkad med Wikipedia", "zh_Hant": "沒有連結到維基百科", "pl": "Brak linku do strony Wikipedii", - "ja": "ウィキペディアと連動していない" + "ja": "ウィキペディアと連動していない", + "fil": "Hindi naka-ugnay sa Wikipedia", + "es": "No enlazado con Wikipedia", + "zh_Hans": "不要连接到维基百科" } } ], @@ -170,7 +185,10 @@ "hu": "Mi a(z) {title()} e-mail címe?", "ca": "Quina és l'adreça de correu electrònic de {title()}?", "ja": "{title()}のEメールアドレスは何ですか?", - "sl": "Kakšen naslov elektronske pošte ima {title()}?" + "sl": "Kakšen naslov elektronske pošte ima {title()}?", + "fil": "Ano ang email address ng {title()}?", + "es": "¿Cual es la direccióm de correo electrónico de {title()}?", + "zh_Hans": "{title()} 的电子邮箱地址为何?" }, "mappings": [ { @@ -206,7 +224,10 @@ "eo": "Kie estas la retejo de {title()}?", "hu": "Mi a weboldala ennek: {title()}?", "ca": "Quina és la web de {title()}?", - "ja": "{title()}のウェブサイトは?" + "ja": "{title()}のウェブサイトは?", + "fil": "Ano ang website ng {title()}?", + "es": "¿Cual es el sitio web de {title()}?", + "zh_Hans": "{title()} 的网站为何?" }, "render": "{website}", "freeform": { @@ -239,7 +260,9 @@ "sv": "Är det här stället tillgängligt med en rullstol?", "zh_Hant": "這個地方可以坐輪椅到達嗎?", "pl": "Czy to miejsce jest dostępne dla osób na wózkach inwalidzkich?", - "ja": "車いすでのアクセスは可能ですか?" + "ja": "車いすでのアクセスは可能ですか?", + "fil": "Kaya bang abutin ang lugar na ito ng naka-wheelchair?", + "es": "¿Este lugar es accesible con una silla de ruedas?" }, "mappings": [ { @@ -263,7 +286,9 @@ "zh_Hant": "這個地方有特別設計給輪椅使用者", "ru": "Это место подходит для людей на инвалидной коляске", "pl": "W tym miejscu zainstalowane zostały udogodnienia dla osób na wózkach inwalidzkich", - "ja": "この場所は、車椅子の方のための特別仕様になっています" + "ja": "この場所は、車椅子の方のための特別仕様になっています", + "fil": "Ang lugar na ito ay angkop sa mga gumagamit ng wheelchair", + "es": "Este lugar está especialmente adaptado para usuarios en sillas de ruedas" } }, { @@ -287,7 +312,9 @@ "zh_Hant": "這個地方坐輪椅很容易到達", "ru": "До этого места легко добраться на инвалидной коляске", "pl": "To miejsce jest łatwo dostępne dla osób na wózkach inwalidzkich", - "ja": "この場所は、車いすで簡単に行くことができます" + "ja": "この場所は、車いすで簡単に行くことができます", + "fil": "Ang lugar na ito ay kayang abutin ng mga naka-wheelchair", + "es": "Este lugar es fácilmente accesible con una silla de ruedas" } }, { @@ -311,7 +338,9 @@ "zh_Hant": "這個地方可以坐輪椅到達,但並不容易", "ru": "До этого места можно добраться, но не просто", "pl": "To miejsce jest dostępne dla osób na wózkach inwalidzkich, ale z pewnymi trudnościami", - "ja": "車いすでこの場所まで行くことは可能ですが、簡単ではありません" + "ja": "車いすでこの場所まで行くことは可能ですが、簡単ではありません", + "fil": "Kayang abutin ang lugar na ito ng mga naka-wheelchair, pero hindi madali", + "es": "Es posible llegar a este lugar con una silla de ruedas, pero no es fácil" } }, { @@ -334,7 +363,9 @@ "sv": "Den här platsen kan inte nås med en rullstol", "zh_Hant": "輪椅無法到達這個地方", "pl": "To miejsce jest niedostępne dla osób na wózkach inwalidzkich", - "ja": "この場所は車いすでは行けません" + "ja": "この場所は車いすでは行けません", + "fil": "Ang lugar na ito ay hindi kayang abutin ng naka-wheelchair", + "es": "No es posible llegar a este lugar con una silla de ruedas" } } ] @@ -356,7 +387,10 @@ "pl": "Czy w tej firmie psy są dozwolone?", "ja": "犬を飼うことができますか?", "id": "Apakah anjing diperbolehkan dalam bisnis ini?", - "sl": "Ali so v tem podjetju dovoljeni psi?" + "sl": "Ali so v tem podjetju dovoljeni psi?", + "fil": "Pinapayagan ba ang mga aso sa establisyementong ito?", + "es": "¿Están permitidos los perros en este negocio?", + "zh_Hans": "犬只是否在这个商业体中允许?" }, "mappings": [ { @@ -379,7 +413,9 @@ "pl": "Psy dozwolone", "ja": "ペット同伴可能", "es": "Se permiten perros", - "sl": "Psi so dovoljeni" + "sl": "Psi so dovoljeni", + "fil": "Pinapayagan ang mga aso", + "zh_Hans": "允许犬只" } }, { @@ -402,7 +438,9 @@ "id": "Anjing tidak diperbolehkan", "ja": "ペット同伴不可", "es": "No se permiten perros", - "sl": "Psi niso dovoljeni" + "sl": "Psi niso dovoljeni", + "fil": "Hindi pinapayagan ang mga aso", + "zh_Hans": "允许犬只" } }, { @@ -423,7 +461,10 @@ "id": "Anjing diperbolehkan, tetapi mereka harus diikat", "pl": "Psy dozwolone, ale muszą być na smyczy", "ja": "ペット同伴可能。ただしリード着用", - "sl": "Psi so dovoljeni, vendar morajo biti na povodcu" + "sl": "Psi so dovoljeni, vendar morajo biti na povodcu", + "fil": "Pinapayagan ang mga aso kung may tali", + "es": "Los perros están permitidos, pero tienen que llevar correa", + "zh_Hans": "允许犬只,但必须拴绳" } }, { @@ -444,7 +485,10 @@ "pl": "Psy dozwolone i mogą biegać bez ograniczeń", "ja": "犬同伴可能、自由に走り回れる", "id": "Anjing diperbolehkan dan dapat berkeliaran dengan bebas", - "sl": "Psi so dovoljeni in lahko prosto tekajo naokoli" + "sl": "Psi so dovoljeni in lahko prosto tekajo naokoli", + "fil": "Pinapayayagan ang mga aso, at malayang makatatakbo", + "es": "Los perros están permitidos y pueden estar sueltos", + "zh_Hans": "允许犬只,且可自由放养" } } ] @@ -468,7 +512,8 @@ "id": "Apakah masih ada sesuatu yang relevan yang tidak dapat Anda berikan dalam pertanyaan sebelumnya? Tambahkan di sini.
    Jangan ulangi fakta yang sudah dinyatakan ", "ja": "前の質問で伝えきれなかった関連事項がまだありますか?ここに追加してください。
    今後表示しない", "es": "¿Aún hay algo relevante que no ha encajado en las preguntas anteriores? Compártalo aquí.
    No repita datos ya expresados", - "sl": "Ali je še kaj pomembnega, česar niste mogli povedati v prejšnjih vprašanjih? Dopišite tukaj.
    Ne ponavljajte že navedenih dejstev" + "sl": "Ali je še kaj pomembnega, česar niste mogli povedati v prejšnjih vprašanjih? Dopišite tukaj.
    Ne ponavljajte že navedenih dejstev", + "fil": "Mayroon pa bang mga bagay na nau-ugnay at hindi mo maibigay sa mga nakaraang tanong? Idagdag dito.
    Huwag ulitin ang mga nai-saad na" }, "render": "{description}", "freeform": { @@ -492,7 +537,10 @@ "hu": "Mikor van nyitva ez: {title()}?", "ca": "Quin és l'horari d'obertura de {title()}?", "ja": "{title()}の営業時間は?", - "sl": "Kakšen odpiralni čas ima {title()}?" + "sl": "Kakšen odpiralni čas ima {title()}?", + "fil": "Anong oras nagbubukas ang {title()}?", + "es": "¿Cuales son las horas de apertura de {title()}?", + "zh_Hans": "{title()} 的开放时间为何?" }, "render": { "de": "

    Öffnungszeiten

    {opening_hours_table(opening_hours)}", @@ -511,7 +559,10 @@ "hu": "

    Nyitva tartás

    {opening_hours_table(opening_hours)}", "ca": "

    Horari d'obertura

    {opening_hours_table(opening_hours)}", "ja": "

    営業時間

    {opening_hours_table(opening_hours)}", - "sl": "

    Odpiralni čas

    {opening_hours_table(opening_hours)}" + "sl": "

    Odpiralni čas

    {opening_hours_table(opening_hours)}", + "fil": "

    Mga oras na bukas

    {opening_hours_table(opening_hours)}", + "es": "

    Horas de apertura

    {opening_hours_table(opening_hours)}", + "zh_Hans": "

    开放时间

    {opening_hours_table(opening_hours)}" }, "freeform": { "key": "opening_hours", @@ -531,7 +582,9 @@ "hu": "Van-e ebben a létesítményben olyan konnektor, amely a bent tartózkodó ügyfelek rendelkezésére áll?", "fr": "Des prises sont elles à disposition des client·e·s en intérieur ?", "pl": "Czy w tym przybytku znajdują się gniazdka elektryczne, gdzie klienci mogą naładować swoje urządzenia?", - "ja": "このアメニティにはコンセントがあり、お客様が店内にいるときにも利用できますか?" + "ja": "このアメニティにはコンセントがあり、お客様が店内にいるときにも利用できますか?", + "fil": "Merong bang mga intsupe (outlet) sa loob, para sa mga suki?", + "es": "¿Esta facilidad tiene enchufes eléctricos, disponibles para los clientes cuando están dentro?" }, "mappings": [ { @@ -546,7 +599,9 @@ "hu": "Számos konnektor áll a belső térben ügyfelek rendelkezésére, ahol elektromos készülékeiket tölthetik", "fr": "Il y a suffisamment de prises disponibles pour les client·e·s en intérieur souhaitant recharger leurs appareils", "pl": "W budynku znajduje się wiele gniazdek elektrycznych, gdzie klienci mogą naładować swoje urządzenia", - "ja": "屋内の席に座っているお客様には、家庭用コンセントがたくさん用意されており、そこで電子機器を充電することができます" + "ja": "屋内の席に座っているお客様には、家庭用コンセントがたくさん用意されており、そこで電子機器を充電することができます", + "fil": "Maraming mga intsupe (sockets) na maaring gamitin ng mga suki na nakaupo sa loob, pang-karga ng kanilang mga elektroniks", + "es": "Hay numerosos enchufes domésticos disponibles para los clientes sentados en el interior, donde pueden cargar sus dispositivos electrónicos" }, "if": "service:electricity=yes" }, @@ -562,7 +617,9 @@ "hu": "Csupán néhány konnektor áll a belső térben ügyfelek rendelkezésére, ahol elektromos készülékeiket tölthetik", "fr": "Il y a peu de prises disponibles pour les client·e·s en intérieur souhaitant recharger leurs appareils", "pl": "W budynku znajduje się kilka gniazdek elektrycznych, gdzie klienci mogą naładować swoje urządzenia", - "ja": "屋内の席に座ったお客様が充電できるよう、コンセントがいくつか用意されています" + "ja": "屋内の席に座ったお客様が充電できるよう、コンセントがいくつか用意されています", + "fil": "May iilang mga intsupe (sockets) na maaring gamitin ng mga suki na nakaupo sa loob, pang-karga ng kanilang mga elektroniks", + "es": "Hay algunos enchufes domésticos disponibles para los clientes sentados en el interior, donde pueden cargar sus dispositivos electrónicos" }, "if": "service:electricity=limited" }, @@ -578,7 +635,9 @@ "zh_Hant": "這邊沒有給客戶用的插座,因此可能需要詢問員工是否能充電", "hu": "A belső térben nincs konnektor az ügyfeleknek, de lehetséges, hogy a személyzet segítségével lehet elektromos eszközt tölteni", "pl": "W budynku nie ma gniazdek elektrycznych dostępnych dla klientów, ale mogą zostać one udostępnione po spytaniu obsługi", - "ja": "屋内にはコンセントがありませんが、スタッフに声をかければ充電できるかもしれません" + "ja": "屋内にはコンセントがありませんが、スタッフに声をかければ充電できるかもしれません", + "fil": "Walang mga intsupe (socket) para sa mga suki, pero maaring tanungin ang kawani kung magpapa-karga", + "es": "No hay enchufes disponibles en el interior para los clientes, pero cargar puede ser posible si se pregunta al personal" }, "if": "service:electricity=ask" }, @@ -594,7 +653,9 @@ "zh_Hant": "這裡客戶座位沒有室內插座", "hu": "A belső térben ülő ügyfeleknek nem áll rendelkezésére konnektor", "pl": "W budynku nie ma gniazdek elektrycznych dostępnych dla klientów", - "ja": "屋内の席には、家庭用コンセントはありません" + "ja": "屋内の席には、家庭用コンセントはありません", + "fil": "Walang mga intsupe (socket) para sa mga suking nakaubo sa loob", + "es": "No hay enchufes domésticos disponibles para los clientes sentados en el interior" }, "if": "service:electricity=no" } @@ -618,7 +679,10 @@ "pl": "Jakie metody płatności są tutaj dostępne?", "ru": "Какие способы оплаты здесь принимают?", "ja": "どのような支払い方法が可能ですか?", - "sl": "Kateri načini plačila so možni tu?" + "sl": "Kateri načini plačila so možni tu?", + "fil": "Anong mga paraang pambayad ang tinatanggap dito?", + "es": "¿Qué métodos de pago se aceptan aquí?", + "zh_Hans": "这里支持哪些支付方式?" }, "multiAnswer": true, "mappings": [ @@ -643,7 +707,10 @@ "pl": "Płatność gotówkowa jest tutaj dostępna", "ru": "Здесь принимают наличными", "ja": "現金利用可能", - "sl": "Tu sprejemajo gotovino" + "sl": "Tu sprejemajo gotovino", + "fil": "Tinatanggap ang salapi rito", + "es": "Aquí se acepta el pago en efectivo", + "zh_Hans": "可用现金" } }, { @@ -667,7 +734,10 @@ "pl": "Płatność kartą jest tutaj dostępna", "ru": "Здесь принимают банковские карты", "ja": "お支払いはこちらで承ります", - "sl": "Tukaj sprejemajo plačilne kartice" + "sl": "Tukaj sprejemajo plačilne kartice", + "fil": "Tinatanggap ang mga tarhetang pambayad dito", + "es": "Aquí se acepta el pago por tarjeta", + "zh_Hans": "可用信用卡" } } ] @@ -688,7 +758,10 @@ "de": "Die Bezahlung erfolgt über eine spezielle App", "fr": "Paiement via une application", "sl": "Plačilo se opravi z namensko aplikacijo", - "ca": "El pagament es fa amb una app dedicada" + "ca": "El pagament es fa amb una app dedicada", + "fil": "Binabayaran gamit ang sariling app", + "es": "El pago se realiza con una aplicación dedicada", + "zh_Hans": "使用专用APP支付" } }, { @@ -703,7 +776,11 @@ "de": "Die Bezahlung erfolgt mit einer Mitgliedskarte", "fr": "Paiement via une carte de membre", "sl": "Plačilo se izvede s člansko izkaznico", - "ca": "El pagament es fa amb una targeta de membre" + "ca": "El pagament es fa amb una targeta de membre", + "fil": "Binabayaran gamit ang membership card", + "es": "El pago se realiza con una tarjeta de membresía", + "nb_NO": "Betaling utføres med et medlemskort", + "zh_Hans": "使用会员卡支付" } } ] @@ -722,7 +799,7 @@ "question": { "nl": "Op welke verdieping bevindt dit punt zich?", "en": "On what level is this feature located?", - "de": "In welchem Stockwerk befindet sich dieses Objekt?", + "de": "Auf welcher Ebene befindet sich dieses Objekt?", "zh_Hant": "此圖徽位於哪個樓層/層級?", "fr": "À quel étage se situe l’élément ?", "pl": "Na jakim poziomie znajduje się ta funkcja?", @@ -734,7 +811,9 @@ "it": "A quale piano si trova questo elemento?", "ca": "A quina planta està situat aquest element?", "sv": "På vilken nivå finns den här funktionen?", - "ja": "この機能は何階にあるのでしょうか?" + "ja": "この機能は何階にあるのでしょうか?", + "fil": "Anong palapag matatagpuan ang tampók?", + "es": "¿En qué nivel se encuentra esta característica?" }, "render": { "en": "Located on the {level}th floor", @@ -752,7 +831,9 @@ "it": "Si trova al piano numero {level}", "ca": "Situat a la planta {level}", "ja": "{level}階にあります", - "sl": "Nahaja se v {level}. nadstropju" + "sl": "Nahaja se v {level}. nadstropju", + "fil": "Natagpuan sa ika-{level} na palapag", + "es": "Localizada en la {level}° planta" }, "freeform": { "key": "level", @@ -778,7 +859,9 @@ "ca": "Situat a planta subterrani", "ja": "地下にあります", "id": "Terletak di bawah tanah", - "sl": "Nahaja se pod zemljo" + "sl": "Nahaja se pod zemljo", + "fil": "Nasa ilalim ng lupa", + "es": "Localizado bajo tierra" }, "hideInAnswer": true }, @@ -802,7 +885,9 @@ "ca": "Situat a planta zero", "ja": "1階にあります", "id": "Terletak di lantai dasar", - "sl": "Nahaja se v pritličju" + "sl": "Nahaja se v pritličju", + "fil": "Nasa unang palapag", + "es": "Localizado en la planta baja" } }, { @@ -826,7 +911,9 @@ "ca": "Situat a planta zero", "ja": "1階にあります", "id": "Terletak di lantai dasar", - "sl": "Nahaja se v pritličju" + "sl": "Nahaja se v pritličju", + "fil": "Nasa unang palapag", + "es": "Localizado en la planta baja" } }, { @@ -849,7 +936,9 @@ "nb_NO": "I andre etasje", "ca": "Situat a primera planta", "ja": "1階にあります", - "sl": "Nahaja se v prvem nadstropju" + "sl": "Nahaja se v prvem nadstropju", + "fil": "Nasa unang palapag", + "es": "Localizado en la primera planta" } }, { @@ -863,7 +952,9 @@ "id": "Terletak di lantai basement pertama", "fr": "Sous-sol", "sl": "Nahaja se v prvi kletni etaži", - "ca": "Localitzat a la planta base" + "ca": "Localitzat a la planta base", + "fil": "Nasa silong", + "es": "Situado en el primer nivel del sótano" } } ] diff --git a/assets/themes/aed/aed.json b/assets/themes/aed/aed.json index 987e2a686..50d0598bd 100644 --- a/assets/themes/aed/aed.json +++ b/assets/themes/aed/aed.json @@ -17,7 +17,8 @@ "sv": "Öppna AED-karta", "pl": "Otwórz mapę AED", "pt_BR": "Abrir mapa AED", - "sl": "Zemljevid defibrilatorjev (AED)" + "sl": "Zemljevid defibrilatorjev (AED)", + "zh_Hans": "Open AED Map" }, "maintainer": "MapComplete", "icon": "./assets/themes/aed/aed.svg", @@ -38,7 +39,8 @@ "pt_BR": "Neste mapa, pode-se encontrar e marcar desfibriladores próximos", "nb_NO": "Defibrillatorer i nærheten", "hu": "Ezen a térképen a közeli defibrillátorokat lehet megtalálni és feltüntetni", - "sl": "Na tem zemljevidu lahko poiščete in označite bližnje defibrilatorje" + "sl": "Na tem zemljevidu lahko poiščete in označite bližnje defibrilatorje", + "zh_Hans": "在这份地图上可以寻找和标记附近的除颤器" }, "version": "2020-08-29", "startLat": 0, diff --git a/assets/themes/artwork/artwork.json b/assets/themes/artwork/artwork.json index b947cddf0..f0b26afec 100644 --- a/assets/themes/artwork/artwork.json +++ b/assets/themes/artwork/artwork.json @@ -14,7 +14,9 @@ "zh_Hant": "開放藝術品地圖", "sv": "Öppen konstverkskarta", "pl": "Otwórz mapę dzieł sztuki", - "nb_NO": "Kunstkort" + "nb_NO": "Kunstkort", + "ca": "Open Artwork Map", + "zh_Hans": "Open Artwork Map" }, "description": { "en": "Welcome to Open Artwork Map, a map of statues, busts, grafittis and other artwork all over the world", @@ -29,7 +31,9 @@ "zh_Hant": "歡迎來到開放藝術品地圖,這份地圖會顯示全世界的雕像、半身像、塗鴉以及其他類型的藝術品", "nb_NO": "Velkommen til det åpne kunstverkskartet, et kart over statuer, byster, grafitti, og andre kunstverk i verden", "hu": "Isten hozta a nyílt műalkotástérképen, a világ minden táján megtalálható szobrok, mellszobrok, graffitik és más műalkotások gyűjtőhelyén", - "pl": "Witaj w Open Artwork Map, mapie pomników, popierś, graffitti i innych dzieł sztuki z całego świata" + "pl": "Witaj w Open Artwork Map, mapie pomników, popierś, graffitti i innych dzieł sztuki z całego świata", + "ca": "Benvingut a Open Artwork Map, un mapa d'estàtues, busts, grafitis i altres obres d'art del tot el món", + "zh_Hans": "欢迎使用Open Artwork Map,一个雕塑、半身像、涂鸦和其他全球艺术品的地图" }, "icon": "./assets/themes/artwork/artwork.svg", "maintainer": "MapComplete", diff --git a/assets/themes/benches/benches.json b/assets/themes/benches/benches.json index c088ca9a5..42616da80 100644 --- a/assets/themes/benches/benches.json +++ b/assets/themes/benches/benches.json @@ -12,7 +12,10 @@ "nb_NO": "Benker", "pt_BR": "Bancadas", "id": "Bangku", - "hu": "Padok" + "hu": "Padok", + "ca": "Bancs", + "es": "Bancos", + "zh_Hans": "长椅" }, "shortDescription": { "en": "A map of benches", @@ -26,18 +29,23 @@ "nb_NO": "Et benkekart", "pt_BR": "Um mapa de bancadas", "hu": "Padtérkép", - "id": "Peta bangku" + "id": "Peta bangku", + "ca": "Un mapa de bancs", + "es": "Un mapa de bancos", + "zh_Hans": "长椅地图" }, "description": { "en": "This map shows all benches that are recorded in OpenStreetMap: Individual benches, and benches belonging to public transport stops or shelters. With an OpenStreetMap account, you can map new benches or edit details of existing benches.", - "de": "Diese Karte zeigt alle Sitzbänke, die in OpenStreetMap eingetragen sind: Einzeln stehende Bänke und Bänke, die zu Haltestellen oder Unterständen gehören. Mit einem OpenStreetMap-Account können Sie neue Bänke eintragen oder Detailinformationen existierender Bänke bearbeiten.", + "de": "Diese Karte zeigt alle Sitzbänke, die in OpenStreetMap eingetragen sind: Alleinstehende Bänke und Bänke, die zu Haltestellen oder Unterständen gehören. Mit einem OpenStreetMap-Konto können Sie neue Bänke eintragen oder Details existierender Bänke bearbeiten.", "fr": "Cette carte affiche les bancs mappés dans OpenStreetMap, entre autres : bancs des transports en commun, bancs publics, etc. À l'aide de votre compte OpenStretMap, vous pourrez ajouter de nouveaux bancs ou modifier les bancs existants.", "nl": "Deze kaart toont alle zitbanken die zijn opgenomen in OpenStreetMap: individuele banken en banken bij bushaltes. Met een OpenStreetMap-account kan je informatie verbeteren en nieuwe zitbanken toevoegen.", "it": "Questa mappa mostra tutte le panchine che sono state aggiunte su OpenStreetMap: panchine individuali e quelle alle fermate del trasporto pubblico o nei ripari. Se disponi di un account OpenStreetMap puoi mappare delle nuove panchine o modificare i dettagli di quelle esistenti.", "ru": "На этой карте показаны все скамейки, записанные в OpenStreetMap: отдельные скамейки, а также скамейки, относящиеся к остановкам общественного транспорта или навесам. Имея учётную запись OpenStreetMap, вы можете наносить на карту новые скамейки или редактировать информацию о существующих скамейках.", "ja": "このマップには、OpenStreetMapに記録されているすべてのベンチが表示されます。個々のベンチ、および公共交通機関の停留所または避難場所に属するベンチです。OpenStreetMapアカウントを使用すると、新しいベンチをマップしたり、既存のベンチの詳細を編集したりできます。", "zh_Hant": "這份地圖顯示開放街圖上所有記錄的長椅:單獨的長椅,屬於大眾運輸站點或涼亭的長椅。只要有開放街圖帳號,你可以新增長椅或是編輯既有長椅的詳細內容。", - "hu": "Ez a térkép megjeleníti az OpenStreetMap-en rögzített összes padot: egyes padokat, valamint tömegközlekedési megállókban vagy menedékhelyeken található padokat. OpenStreetMap-fiókkal Ön is felrajzolhat új padokat, vagy szerkesztheti a meglévő padok részleteit." + "hu": "Ez a térkép megjeleníti az OpenStreetMap-en rögzített összes padot: egyes padokat, valamint tömegközlekedési megállókban vagy menedékhelyeken található padokat. OpenStreetMap-fiókkal Ön is felrajzolhat új padokat, vagy szerkesztheti a meglévő padok részleteit.", + "ca": "Aquest mapa mostra tots els bancs que hi ha a OpenStreetMap: bancs individuals i els bancs que hi ha a parades o refugis de transport públic. Amb un compte d'OpenStreetMap pots afegir nous bancs o editar detalls dels existents.", + "es": "Este mapa muestra todos los bancos que están grabados en OpenStreetMap: Bancos individuales, bancos que pertenecen a paradas o marquesinas del transporte público. Con una cuenta de OpenStreetMap, puedes mapear nuevos bancos o editar detalles de bancos existentes." }, "maintainer": "Florian Edelmann", "icon": "./assets/themes/benches/bench_poi.svg", diff --git a/assets/themes/bicycle_rental/bicycle_rental.json b/assets/themes/bicycle_rental/bicycle_rental.json index 152f1db36..af25c533e 100644 --- a/assets/themes/bicycle_rental/bicycle_rental.json +++ b/assets/themes/bicycle_rental/bicycle_rental.json @@ -5,20 +5,25 @@ "nl": "Fietsverhuur", "de": "Fahrradverleih", "id": "Sewa sepeda", - "fr": "Location de vélos" + "fr": "Location de vélos", + "ca": "Lloguer de bicicletes", + "es": "Alquiler de bicicletas", + "nb_NO": "Sykkelutleie" }, "shortDescription": { "en": "A map with bicycle rental stations and bicycle rental shops", "nl": "Een kaart met fietsverhuurpunten en fietsverhuurzaken", "de": "Eine Karte mit Fahrradverleihstationen und Fahrradverleihern", "id": "Peta dengan stasiun persewaan sepeda dan toko penyewaan sepeda", - "fr": "Une carte avec des stations et magasins de location de vélos" + "fr": "Une carte avec des stations et magasins de location de vélos", + "es": "Un mapa con estaciones de alquiler de bicicletas y tiendas de alquiler de bicicletas" }, "description": { "en": "On this map, you'll find the many bicycle rental stations as they are known by OpenStreetMap", "nl": "Op deze kaart vind je verschillende fietsverhuurpunten en fietsverhuurzaken", "de": "Auf dieser Karte finden Sie die vielen Fahrradverleihstationen, wie sie auf OpenStreetMap eingetragen wurden", - "fr": "Vous trouverez sur cette carte toutes les stations de location de vélo telles qu'elles sont référencées dans OpenStreetMap" + "fr": "Vous trouverez sur cette carte toutes les stations de location de vélo telles qu'elles sont référencées dans OpenStreetMap", + "es": "En este mapa, encontrarás numerosas estaciones de alquiler de bicicletas que son conocidas por OpenStreetMap" }, "maintainer": "", "icon": "./assets/themes/bicycle_rental/logo.svg", diff --git a/assets/themes/binoculars/binoculars.json b/assets/themes/binoculars/binoculars.json index 76834bad2..d6cc85fc8 100644 --- a/assets/themes/binoculars/binoculars.json +++ b/assets/themes/binoculars/binoculars.json @@ -7,7 +7,9 @@ "it": "Binocoli", "nb_NO": "Kikkerter", "zh_Hant": "望遠鏡", - "hu": "Távcsövek" + "hu": "Távcsövek", + "fr": "Jumelles", + "es": "Binoculares" }, "shortDescription": { "en": "A map with fixed binoculars", @@ -16,7 +18,9 @@ "it": "Una cartina dei binocoli pubblici fissi", "nb_NO": "Et kart over fastmonterte kikkerter", "zh_Hant": "固定望遠鏡的地圖", - "hu": "Rögzített távcsövek (binokulárok) térképe" + "hu": "Rögzített távcsövek (binokulárok) térképe", + "fr": "Une carte de jumelles panoramiques", + "es": "Un mapa con prismáticos fijos" }, "description": { "en": "A map with binoculars fixed in place with a pole. It can typically be found on touristic locations, viewpoints, on top of panoramic towers or occasionally on a nature reserve.", @@ -24,7 +28,9 @@ "de": "Eine Karte für festinstallierte Ferngläsern. Man findet sie meist an touristischen Orten, Aussichtspunkten, Aussichtstürmen oder gelegentlich in Naturschutzgebieten.", "it": "Una cartina dei binocoli su un palo fissi in un luogo. Si trovano tipicamente nei luoghi turistici, nei belvedere, in cima a torri panoramiche oppure occasionalmente nelle riserve naturali.", "zh_Hant": "固定一地的望遠鏡地圖,特別是能夠在旅遊景點、觀景點、城鎮環景點,或是自然保護區找到。", - "hu": "Rúdra rögzített távcsövek térképe. Jellemzően turisztikailag érdekes, panorámás helyeken, kilátótornyok tetején vagy természetvédelmi területen találhatók." + "hu": "Rúdra rögzített távcsövek térképe. Jellemzően turisztikailag érdekes, panorámás helyeken, kilátótornyok tetején vagy természetvédelmi területen találhatók.", + "fr": "Une carte des longue-vues fixes. Se trouve typiquement sur les sites touristiques, les points de vue, les tours panoramiques ou dans les réserves naturelles.", + "es": "Un mapa con prismáticos fijos en un poste. Suele encontrarse en lugares turísticos, miradores, en lo alto de torres panorámicas u ocasionalmente en una reserva natural." }, "maintainer": "", "icon": "./assets/layers/binocular/telescope.svg", diff --git a/assets/themes/bookcases/bookcases.json b/assets/themes/bookcases/bookcases.json index ada15c938..aa86a1139 100644 --- a/assets/themes/bookcases/bookcases.json +++ b/assets/themes/bookcases/bookcases.json @@ -13,7 +13,9 @@ "it": "Mappa libera delle microbiblioteche", "pt_BR": "Abrir Mapa de Estantes", "nb_NO": "Kart over åpne bokhyller", - "hu": "Könyvespolctérkép" + "hu": "Könyvespolctérkép", + "ca": "Open Bookcase Map", + "es": "Mapa de Librerías Abiertas" }, "description": { "en": "A public bookcase is a small streetside cabinet, box, old phone booth or some other objects where books are stored. Everyone can place or take a book. This map aims to collect all these bookcases. You can discover new bookcases nearby and, with a free OpenStreetMap account, quickly add your favourite bookcases.", @@ -24,7 +26,8 @@ "ja": "公共の本棚とは、本が保管されている小さな街角のキャビネット、箱、古い電話のトランク、その他の物のことです。誰でも本を置いたり持ったりすることができます。このマップは、すべての公共の本棚を収集することを目的としています。近くで新しい本棚を見つけることができ、無料のOpenStreetMapアカウントを使えば、お気に入りの本棚を簡単に追加できます。", "zh_Hant": "公共書架是街邊箱子、盒子、舊的電話亭或是其他存放書本的物件,每一個人都能放置或拿取書本。這份地圖收集所有類型的書架,你可以探索你附近新的書架,同時也能用免費的開放街圖帳號來快速新增你最愛的書架。", "it": "Una libreria pubblica è una piccola cabina a lato della strada, un locale, una vecchia cabina telefonica o qualche altro luogo in cui sono tenuti libri. Chiunque può lasciare o prendere libri. Scopo della mappa è individuarle. Se scopri nuove librerie nelle vicinanze, puoi facilmente aggiungerle con un account OpenStreetMap.", - "hu": "A nyilvános könyvespolc egy kis utcai szekrény, doboz, régi telefonfülke vagy más tárgy, ahol könyveket tárolnak. Bárki tehet rá vagy vihet el róla könyvet. Ez a térkép ezeket a könyvespolcokat kívánja összegyűjteni. Ha felfedezett egy új könyvespolcot a közelben, akkor egy ingyenes OpenStreetMap-fiókkal gyorsan fel is rajzolhatja a térképre." + "hu": "A nyilvános könyvespolc egy kis utcai szekrény, doboz, régi telefonfülke vagy más tárgy, ahol könyveket tárolnak. Bárki tehet rá vagy vihet el róla könyvet. Ez a térkép ezeket a könyvespolcokat kívánja összegyűjteni. Ha felfedezett egy új könyvespolcot a közelben, akkor egy ingyenes OpenStreetMap-fiókkal gyorsan fel is rajzolhatja a térképre.", + "es": "Una librería pública es un pequeño armario en la calle, una caja, una vieja cabina telefónica o algún otro objeto donde se guardan libros. Todo el mundo puede colocar o coger un libro. Este mapa pretende recoger todas estas librerías. Puedes descubrir nuevas librerías cercanas y, con una cuenta gratuita de OpenStreetMap, añadir rápidamente tus librerías favoritas." }, "icon": "./assets/themes/bookcases/bookcase.svg", "startLat": 0, diff --git a/assets/themes/cafes_and_pubs/cafes_and_pubs.json b/assets/themes/cafes_and_pubs/cafes_and_pubs.json index fba4ea7d1..9cdbff2f3 100644 --- a/assets/themes/cafes_and_pubs/cafes_and_pubs.json +++ b/assets/themes/cafes_and_pubs/cafes_and_pubs.json @@ -9,12 +9,18 @@ "id": "Kafe dan pub", "zh_Hant": "咖啡廳與酒吧", "ru": "Кафе и пабы", - "hu": "Kávézók és kocsmák" + "hu": "Kávézók és kocsmák", + "ca": "Cafés i bars", + "es": "Cafeterías y pubs", + "fr": "Cafés et pubs" }, "description": { "en": "Pubs and bars", "nl": "Cafés, kroegen en drinkgelegenheden", - "de": "Kneipen und Bars" + "de": "Kneipen und Bars", + "ca": "Bars i pubs", + "es": "Pubs y bares", + "fr": "Bars et pubs" }, "maintainer": "", "icon": "./assets/layers/cafe_pub/pub.svg", diff --git a/assets/themes/campersite/campersite.json b/assets/themes/campersite/campersite.json index b3867f40f..74c7169c7 100644 --- a/assets/themes/campersite/campersite.json +++ b/assets/themes/campersite/campersite.json @@ -10,7 +10,8 @@ "zh_Hant": "露營地點", "pt_BR": "Locais de acampamento", "de": "Wohnmobilstellplätze", - "hu": "Lakóautós megállóhelyek" + "hu": "Lakóautós megállóhelyek", + "ca": "Llocs d'acampada" }, "shortDescription": { "en": "Find sites to spend the night with your camper", @@ -33,7 +34,8 @@ "nl": "Deze website verzamelt en toont alle officiële plaatsen waar een camper mag overnachten en afvalwater kan lozen. Ook jij kan extra gegevens toevoegen, zoals welke services er geboden worden en hoeveel dit kot, ook afbeeldingen en reviews kan je toevoegen. De data wordt op OpenStreetMap opgeslagen en is dus altijd gratis te hergebruiken, ook door andere applicaties.", "fr": "Ce site collecte les zones de camping officielles ainsi que les aires de vidange. Il est possible d’ajouter des détails à propos des services proposés ainsi que leurs coûts. Ajoutez vos images et avis. C’est un site et une application. Les données sont stockées sur OpenStreetMap, elles seront toujours gratuites et peuvent être réutilisées par n’importe quelle application.", "de": "Eine Karte für offizielle Wohnmobilstellplätze und Orte zur Entsorgung von Schmutzwasser. Sie können Details über die angebotenen Dienstleistungen und die Kosten hinzufügen, oder Bilder und Bewertungen ergänzen. Dies ist eine Webseite und eine Webapp. Die Daten werden in OpenStreetMap gespeichert, so dass sie für immer kostenlos sind und von jeder App weiterverwendet werden können.", - "hu": "Ez az oldal az összes olyan hivatalos lakóautós megállóhelyet és helyet gyűjti össze, ahol szürke és fekete szennyvizet lehet üríteni. Hozzáadhat részleteket a nyújtott szolgáltatásokról és a költségekről, valamint képeket és értékeléseket. Ez egyszerre egy weboldal és egy webes alkalmazás. Az adatokat az OpenStreetMapen tároljuk, így mindig ingyenesek lesznek, és bármelyik alkalmazás újra felhasználhatja őket." + "hu": "Ez az oldal az összes olyan hivatalos lakóautós megállóhelyet és helyet gyűjti össze, ahol szürke és fekete szennyvizet lehet üríteni. Hozzáadhat részleteket a nyújtott szolgáltatásokról és a költségekről, valamint képeket és értékeléseket. Ez egyszerre egy weboldal és egy webes alkalmazás. Az adatokat az OpenStreetMapen tároljuk, így mindig ingyenesek lesznek, és bármelyik alkalmazás újra felhasználhatja őket.", + "es": "Este sitio recoge todos los lugares oficiales de parada de caravanas y los lugares donde se pueden verter las aguas grises y negras. Puedes añadir detalles sobre los servicios prestados y el coste. Añade fotos y reseñas. Este es un sitio web y una aplicación web. Los datos se almacenan en OpenStreetMap, por lo que serán gratuitos para siempre y podrán ser reutilizados por cualquier aplicación." }, "maintainer": "joost schouppe", "icon": "./assets/themes/campersite/caravan.svg", @@ -57,7 +59,9 @@ "pt_BR": "Locais de acampamento", "de": "Wohnmobilstellplätze", "hu": "Lakóautós megállóhely", - "id": "Tempat camping" + "id": "Tempat camping", + "ca": "Llocs d'acampada", + "es": "Sitios de Acampada" }, "minzoom": 10, "source": { @@ -113,7 +117,9 @@ "pt_BR": "Locais de acampamento", "de": "Wohnmobilstellplätze", "hu": "Lakóautós megállóhelyek", - "id": "Tempat camping" + "id": "Tempat camping", + "ca": "llocs d'acampada", + "es": "Sitios de acampada" }, "tagRenderings": [ "images", @@ -128,7 +134,8 @@ "nl": "Deze plaats heet {name}", "pt_BR": "Este lugar é chamado de {name}", "de": "Dieser Ort heißt {name}", - "id": "Tempat ini disebut {name}" + "id": "Tempat ini disebut {name}", + "es": "Este lugar se llama {name}" }, "question": { "en": "What is this place called?", @@ -140,7 +147,8 @@ "zh_Hant": "這個地方叫做什麼?", "nl": "Wat is de naam van deze plaats?", "pt_BR": "Qual o nome deste lugar?", - "de": "Wie heißt dieser Ort?" + "de": "Wie heißt dieser Ort?", + "es": "¿Cómo se llama este lugar?" }, "freeform": { "key": "name" @@ -158,7 +166,8 @@ "zh_Hant": "這個地方收費嗎?", "nl": "Moet men betalen om deze camperplaats te gebruiken?", "pt_BR": "Este lugar cobra alguma taxa?", - "de": "Wird hier eine Gebühr erhoben?" + "de": "Wird hier eine Gebühr erhoben?", + "es": "¿Este lugar cobra una tarifa?" }, "mappings": [ { @@ -177,7 +186,8 @@ "fr": "L’utilisation est payante", "pt_BR": "Você precisa pagar para usar", "de": "Sie müssen für die Nutzung bezahlen", - "id": "Anda perlu membayar untuk menggunakannya" + "id": "Anda perlu membayar untuk menggunakannya", + "es": "Necesitas pagar por su uso" } }, { @@ -198,7 +208,8 @@ "zh_Hant": "可以免費使用", "nl": "Kan gratis gebruikt worden", "pt_BR": "Pode ser usado de graça", - "de": "Nutzung kostenlos" + "de": "Nutzung kostenlos", + "es": "Se puede usar de manera gratuita" }, "addExtraTags": [ "charge=" @@ -217,7 +228,8 @@ "nl": "Deze plaats vraagt {charge}", "fr": "Ce site fait payer {charge}", "pt_BR": "Este lugar cobra {charge}", - "de": "Die Gebühr beträgt {charge}" + "de": "Die Gebühr beträgt {charge}", + "es": "Este lugar cobra {charge}" }, "question": { "en": "How much does this place charge?", @@ -229,7 +241,8 @@ "zh_Hant": "這個地方收多少費用?", "nl": "Hoeveel kost deze plaats?", "pt_BR": "Quanto este lugar cobra?", - "de": "Wie hoch ist die Gebühr an diesem Ort?" + "de": "Wie hoch ist die Gebühr an diesem Ort?", + "es": "¿Cuánto cobra este lugar?" }, "freeform": { "key": "charge" @@ -252,7 +265,8 @@ "fr": "Ce site possède-t’il un lieu de vidange ?", "pt_BR": "Este local tem uma estação de aterro sanitário?", "de": "Hat dieser Ort eine sanitäre Entsorgungsstation?", - "id": "Apakah tempat ini memiliki tempat pembuangan sanitasi?" + "id": "Apakah tempat ini memiliki tempat pembuangan sanitasi?", + "es": "¿Este lugar tiene un vertedero sanitario?" }, "mappings": [ { @@ -270,7 +284,8 @@ "zh_Hant": "這個地方有衛生設施", "pt_BR": "Este local tem uma estação de aterro sanitário", "de": "Dieser Ort hat eine sanitäre Entsorgungsstation", - "id": "Tempat ini memiliki tempat pembuangan sanitasi" + "id": "Tempat ini memiliki tempat pembuangan sanitasi", + "es": "Este lugar tiene un vertedero sanitario" } }, { @@ -288,7 +303,8 @@ "fr": "Ce site ne possède pas de lieu de vidange", "pt_BR": "Este local não tem uma estação de aterro sanitário", "de": "Dieser Ort hat keine sanitäre Entsorgungsstation", - "id": "Tempat ini tidak memiliki tempat pembuangan sampah sanitasi" + "id": "Tempat ini tidak memiliki tempat pembuangan sampah sanitasi", + "es": "Este lugar no tiene vertedero sanitario" } } ] @@ -303,7 +319,8 @@ "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", - "nl": "{capacity} campers kunnen deze plaats tegelijk gebruiken" + "nl": "{capacity} campers kunnen deze plaats tegelijk gebruiken", + "es": "{capacity} los campistas pueden utilizar este lugar al mismo tiempo" }, "question": { "en": "How many campers can stay here? (skip if there is no obvious number of spaces or allowed vehicles)", @@ -314,7 +331,8 @@ "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)", - "nl": "Hoeveel campers kunnen hier overnachten? (sla dit over als er geen duidelijk aantal plaatsen of aangeduid maximum is)" + "nl": "Hoeveel campers kunnen hier overnachten? (sla dit over als er geen duidelijk aantal plaatsen of aangeduid maximum is)", + "es": "¿Cuántos campistas pueden alojarse aquí? (omitir si no hay un número evidente de plazas o vehículos permitidos)" }, "freeform": { "key": "capacity", @@ -334,7 +352,8 @@ "zh_Hant": "這個地方有提網路連線嗎?", "pt_BR": "Este lugar fornece acesso a internet?", "de": "Ist an diesem Ort ein Internetzugang vorhanden?", - "nl": "Biedt deze plaats internettoegang?" + "nl": "Biedt deze plaats internettoegang?", + "es": "¿Este lugar tiene acceso a internet?" }, "mappings": [ { @@ -353,7 +372,9 @@ "fr": "Il y a un accès internet", "pt_BR": "Há acesso à internet", "de": "Internetzugang ist vorhanden", - "nl": "Er is internettoegang" + "nl": "Er is internettoegang", + "ca": "Hi ha accés a internet", + "es": "Hay acceso a internet" } }, { @@ -373,7 +394,8 @@ "fr": "Il y a un accès internet", "pt_BR": "Há acesso à Internet", "de": "Internetzugang ist vorhanden", - "nl": "Er is internettoegang" + "nl": "Er is internettoegang", + "es": "Hay acceso a internet" }, "hideInAnswer": true }, @@ -393,7 +415,8 @@ "fr": "Il n’y a pas d’accès internet", "pt_BR": "Não há acesso à internet", "de": "Kein Internetzugang vorhanden", - "nl": "Er is geen internettoegang" + "nl": "Er is geen internettoegang", + "es": "No hay acceso a internet" } } ] @@ -408,7 +431,9 @@ "zh_Hant": "你需要為網路連線付費嗎?", "fr": "L’accès internet est-il payant ?", "pt_BR": "Você tem que pagar pelo acesso à internet?", - "de": "Ist der Internetzugang gebührenpflichtig?" + "de": "Ist der Internetzugang gebührenpflichtig?", + "nl": "Moet je betalen voor internettoegang?", + "es": "¿Tienes que pagar por el acceso a internet?" }, "mappings": [ { @@ -425,7 +450,9 @@ "zh_Hant": "你需要額外付費來使用網路連線", "fr": "L’accès internet est en supplément", "pt_BR": "Você precisa pagar um extra pelo acesso à internet", - "de": "Der Internetzugang ist gebührenpflichtig" + "de": "Der Internetzugang ist gebührenpflichtig", + "nl": "Je moet extra betalen voor internettoegang", + "es": "Tienes que pagar a mayores por el acceso a internet" } }, { @@ -442,7 +469,9 @@ "zh_Hant": "你不需要額外付費來使用網路連線", "fr": "L’accès internet est inclus", "pt_BR": "Você não precisa pagar um extra pelo acesso à internet", - "de": "Der Internetzugang ist kostenlos" + "de": "Der Internetzugang ist kostenlos", + "nl": "Je hoeft niet extra te betalen voor internettoegang", + "es": "No tienes que pagar a mayores por el acceso a internet" } } ], @@ -486,7 +515,8 @@ "pt_BR": "Este lugar tem banheiros", "de": "Dieser Ort verfügt über Toiletten", "nl": "Deze plaats heeft toiletten", - "hu": "Itt van WC" + "hu": "Itt van WC", + "es": "Este lugar cuenta con sanitarios" } }, { @@ -507,7 +537,8 @@ "pt_BR": "Este lugar não tem banheiros", "de": "Dieser Ort verfügt nicht über Toiletten", "nl": "Deze plaats heeft geen toiletten", - "hu": "Itt nincs WC" + "hu": "Itt nincs WC", + "es": "Este lugar no tiene sanitarios" } } ] @@ -555,7 +586,8 @@ "it": "Questo luogo offre spazi per il noleggio a lungo termine?", "fr": "Ce site permet-il la location longue durée ?", "pt_BR": "Este lugar oferece vagas para aluguel a longo prazo?", - "de": "Gibt es a diesem Ort Plätze für Dauercamper?" + "de": "Gibt es a diesem Ort Plätze für Dauercamper?", + "es": "¿Este lugar ofrece huecos para alquilar a largo plazo?" }, "mappings": [ { @@ -572,7 +604,8 @@ "it": "Sì, ci sono spazi per il noleggio a lungo termine, ma puoi anche pagare per singola giornata", "fr": "Oui, mais il est possible d’y passer seulement une nuit", "pt_BR": "Sim, há alguns pontos para aluguel a longo prazo, mas você também pode ficar em uma base diária", - "de": "Ja, es gibt einige Plätze für Langzeitmieten, aber Sie können auch tageweise bleiben" + "de": "Ja, es gibt einige Plätze für Langzeitmieten, aber Sie können auch tageweise bleiben", + "es": "Sí, hay algunas plazas de alquiler a largo plazo, pero también puedes alojarte por días" } }, { @@ -589,7 +622,8 @@ "it": "No, non ci sono ospiti a lungo termine qui", "fr": "Non, il n’y a pas de résidents permanents", "pt_BR": "Não, não há hóspedes permanentes aqui", - "de": "Nein, hier gibt es keine Dauergäste" + "de": "Nein, hier gibt es keine Dauergäste", + "es": "No, no hay huéspedes permanentes aquí" } }, { @@ -605,7 +639,8 @@ "zh_Hant": "如果有長期租用合約才有可能待下來(如果你選擇這個地方則會在這份地圖消失)", "it": "Puoi soggiornare qui solo se hai un contratto a lungo termine (se selezioni questa opzione, questo luogo sarà rimosso da questa mappa)", "fr": "C’est possible sous contrat (Cette option fera disparaître le site de la carte)", - "de": "Es sind nur Plätze für Dauercamper vorhanden (wenn Sie diese Antwort auswählen, wird dieser Ort wird von der Karte verschwinden)" + "de": "Es sind nur Plätze für Dauercamper vorhanden (wenn Sie diese Antwort auswählen, wird dieser Ort wird von der Karte verschwinden)", + "es": "Solo es posible permanecer aquí si tienes un contrato a largo plazo (este lugar desaparecerá de este mapa si escoges esto)" } } ] @@ -621,7 +656,8 @@ "fr": "Plus de détails à propos du site : {description}", "pt_BR": "Mais detalhes sobre este lugar: {description}", "de": "Mehr Details über diesen Ort: {description}", - "nl": "Meer details over deze plaats: {description}" + "nl": "Meer details over deze plaats: {description}", + "es": "Más detalles sobre este lugar:{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)", @@ -631,7 +667,8 @@ "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)", - "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)" + "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)", + "es": "¿Te gustaría añadir una descripción general de este lugar? (No repitas información previamente preguntada o mostrada arriba. Por favor mantenla objetiva - las opiniones van en la de opiniones)" }, "freeform": { "key": "description", @@ -657,7 +694,9 @@ "pt_BR": "uma local de acampamento", "de": "eine wohnmobilstellplatz", "nl": "een camperplaats", - "hu": "lakóautós megállóhely" + "hu": "lakóautós megállóhely", + "ca": "un lloc d'acampada", + "es": "Un camping" }, "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 ", @@ -668,7 +707,8 @@ "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. ", "zh_Hant": "新增正式露營地點,通常是設計給過夜的露營者的地點。看起來像是真的露營地或是一般的停車場,而且也許沒有任何指標,但在城鎮被定議地點。如果一般給露營者的停車場並不是用來過夜,則不是露營地點 ", - "hu": "Új hivatalos lakóautóhely hozzáadása. Ez arra vannak kijelölve, hogy lakóautóval ott éjszakázzunk. Lehet, hogy úgy néz ki, mint egy igazi kemping, de az is lehet, hogy csak olyan, mint egy parkoló. Előfordulhat, hogy egyáltalán nem jelzik őket, hanem csak egy önkormányzati határozatban vannak kijelölve. A lakóautósoknak szánt olyan hagyományos parkolók, ahol nem várhatóan nem fognak éjszakázni, -nem minősül- lakóautóhelynek. " + "hu": "Új hivatalos lakóautóhely hozzáadása. Ez arra vannak kijelölve, hogy lakóautóval ott éjszakázzunk. Lehet, hogy úgy néz ki, mint egy igazi kemping, de az is lehet, hogy csak olyan, mint egy parkoló. Előfordulhat, hogy egyáltalán nem jelzik őket, hanem csak egy önkormányzati határozatban vannak kijelölve. A lakóautósoknak szánt olyan hagyományos parkolók, ahol nem várhatóan nem fognak éjszakázni, -nem minősül- lakóautóhelynek. ", + "es": "Añade un nuevo sitio de acampada oficial. Son lugares designados para pasar la noche con tu caravana. Pueden parecerse a un camping real o simplemente a un aparcamiento. Puede que no estén señalizados en absoluto, sino que simplemente estén definidos en una decisión municipal. Un aparcamiento normal destinado a los campistas en el que no se espera que se pase la noche, no es un camping. " } } ], diff --git a/assets/themes/charging_stations/charging_stations.json b/assets/themes/charging_stations/charging_stations.json index ec4fb9dbb..89014e367 100644 --- a/assets/themes/charging_stations/charging_stations.json +++ b/assets/themes/charging_stations/charging_stations.json @@ -10,7 +10,9 @@ "de": "Ladestationen", "nb_NO": "Ladestasjoner", "ru": "Зарядные станции", - "hu": "Elektromos töltőpontok" + "hu": "Elektromos töltőpontok", + "ca": "Estacions de càrrega", + "fr": "Points de recharge" }, "shortDescription": { "en": "A worldwide map of charging stations", @@ -21,7 +23,8 @@ "de": "Eine weltweite Karte mit Ladestationen", "nb_NO": "Et verdensomspennende kart over ladestasjoner", "ru": "Карта зарядных станций по всему миру", - "hu": "Elektromos töltőpontok világtérképe" + "hu": "Elektromos töltőpontok világtérképe", + "fr": "Une carte mondiale des points de recharge" }, "description": { "en": "On this open map, one can find and mark information about charging stations", @@ -29,8 +32,9 @@ "ja": "このオープンマップでは充電ステーションに関する情報を見つけてマークすることができます", "ru": "На этой карте вы можно найти и отметить информацию о зарядных станциях", "zh_Hant": "在這份開放地圖上,你可以尋找與標示充電站的資訊", - "de": "Auf dieser freien Karte kann man Informationen über Ladestationen finden und hinzufügen", - "hu": "Ezen a térképen a elektromos töltőpontokról szóló információkat lehet megtalálni és megadni" + "de": "Auf dieser freien Karte kann man Informationen zu Ladestationen finden und hinzufügen", + "hu": "Ezen a térképen a elektromos töltőpontokról szóló információkat lehet megtalálni és megadni", + "fr": "Sur cette carte l’on trouve et ajoute des informations sur les points de recharge" }, "maintainer": "", "icon": "./assets/themes/charging_stations/logo.svg", diff --git a/assets/themes/climbing/climbing.json b/assets/themes/climbing/climbing.json index 9dce07814..3723d6b51 100644 --- a/assets/themes/climbing/climbing.json +++ b/assets/themes/climbing/climbing.json @@ -10,7 +10,8 @@ "nb_NO": "Åpent klatrekart", "it": "Mappa aperta per le arrampicate", "fr": "Open Climbing Map", - "hu": "Mászótérkép" + "hu": "Mászótérkép", + "ca": "Open Climbing Map" }, "description": { "nl": "Op deze kaart vind je verschillende klimgelegenheden, zoals klimzalen, bolderzalen en klimmen in de natuur", @@ -42,999 +43,17 @@ "startZoom": 1, "widenFactor": 1.5, "layers": [ - { - "id": "climbing_club", - "name": { - "de": "Klettervereine", - "nl": "Klimclub", - "en": "Climbing club", - "ru": "Клуб скалолазания", - "ja": "クライミングクラブ", - "zh_Hant": "攀岩社團", - "nb_NO": "Klatreklubb", - "fr": "Club d’escalade", - "it": "Club di arrampicata", - "hu": "Mászóegyesület" - }, - "minzoom": 10, - "source": { - "osmTags": { - "or": [ - "club=climbing", - { - "and": [ - "sport=climbing", - { - "or": [ - "office~*", - "club~*" - ] - } - ] - } - ] - } - }, - "title": { - "render": { - "en": "Climbing club", - "nl": "Klimclub", - "de": "Kletterverein", - "ru": "Клуб скалолазания", - "ja": "クライミングクラブ", - "zh_Hant": "攀岩社團", - "nb_NO": "Klatreklubb", - "fr": "Club d’escalade", - "it": "Club di arrampicata" - }, - "mappings": [ - { - "if": "office~*", - "then": { - "nl": "Klimorganisatie", - "en": "Climbing NGO", - "de": "Kletter-Organisation", - "ja": "クライミングNGO", - "zh_Hant": "攀岩 NGO", - "fr": "Association d’escalade", - "it": "Associazione di arrampicata", - "hu": "Mászószervezet" - } - } - ] - }, - "description": { - "de": "Ein Kletterverein oder -organisation", - "nl": "Een klimclub of organisatie", - "en": "A climbing club or organisation", - "ja": "クライミングクラブや団体", - "zh_Hant": "攀岩社團或組織", - "nb_NO": "En klatreklubb eller organisasjoner", - "fr": "Club ou association d’escalade", - "it": "Un club o associazione di arrampacata", - "hu": "Mászóegyesület vagy -szervezet" - }, - "tagRenderings": [ - { - "render": { - "en": "{name}", - "nl": "{name}", - "de": "{name}", - "ca": "{name}", - "fr": "{name}", - "id": "{name}", - "ru": "{name}", - "ja": "{name}", - "zh_Hant": "{name}", - "it": "{name}", - "hu": "{name}" - }, - "question": { - "en": "What is the name of this climbing club or NGO?", - "de": "Wie lautet der Name dieses Vereins oder Organisation?", - "nl": "Wat is de naam van deze klimclub?", - "ja": "この登山クラブやNGOの名前は何ですか?", - "fr": "Quel est le nom du club ou de l’association ?", - "it": "Qual è il nome di questo club o associazione di arrampicata?", - "hu": "Mi a neve ennek a mászóegyesületnek vagy szervezetnek?" - }, - "freeform": { - "key": "name" - }, - "id": "climbing_club-name" - }, - "website", - "email", - "phone", - "opening_hours" - ], - "presets": [ - { - "tags": [ - "club=sport", - "sport=climbing" - ], - "title": { - "de": "eine kletterverein", - "en": "a climbing club", - "nl": "een klimclub", - "ja": "クライミングクラブ", - "nb_NO": "en klatreklubb", - "ru": "Клуб скалолазания", - "fr": "une club d’escalade", - "it": "una club di arrampicata", - "hu": "Mászóegyesület" - }, - "description": { - "de": "Ein Kletterverein", - "nl": "Een klimclub", - "en": "A climbing club", - "ja": "クライミングクラブ", - "nb_NO": "En klatreklubb", - "ru": "Клуб скалолазания", - "fr": "Un club d’escalade", - "it": "Un club di arrampicata", - "hu": "Egy mászóegyesület" - } - }, - { - "tags": [ - "office=ngo", - "sport=climbing" - ], - "title": { - "de": "eine eine kletter-organisation", - "en": "a climbing ngo", - "nl": "een een klimorganisatie", - "ja": "クライミングNGO", - "fr": "une association d’escalade", - "it": "una associazione di arrampicata", - "hu": "Mászószervezet" - }, - "description": { - "de": "Eine Organisation, die sich mit dem Klettern beschäftigt", - "nl": "Een VZW die werkt rond klimmen", - "en": "An NGO working around climbing", - "ja": "登山に関わるNGO", - "fr": "Une association d’escalade", - "it": "Un’associazione che ha a che fare con l’arrampicata", - "hu": "Mászással foglalkozó civil szervezet" - } - } - ], - "mapRendering": [ - { - "icon": { - "render": "./assets/themes/climbing/club.svg" - }, - "iconBadges": [ - { - "if": "opening_hours~*", - "then": "isOpen" - } - ], - "iconSize": { - "render": "40,40,center" - }, - "location": [ - "point", - "centroid" - ], - "label": { - "mappings": [ - { - "if": "name~*", - "then": "
    {name}
    " - } - ] - } - } - ] - }, - { - "id": "climbing_gym", - "name": { - "de": "Kletterhallen", - "en": "Climbing gyms", - "nl": "Klimzalen", - "ja": "クライミングジム", - "fr": "Salle d’escalade", - "it": "Palestre di arrampicata", - "ru": "Комплексы скалолазания" - }, - "minzoom": 10, - "source": { - "osmTags": { - "and": [ - "sport=climbing", - "leisure=sports_centre" - ] - } - }, - "title": { - "render": { - "nl": "Klimzaal", - "de": "Kletterhalle", - "en": "Climbing gym", - "ja": "クライミングジム", - "fr": "Salle d’escalade", - "it": "Palestra di arrampicata", - "ru": "Комплекс скалолазания" - }, - "mappings": [ - { - "if": "name~*", - "then": { - "nl": "Klimzaal {name}", - "de": "Kletterhalle {name}", - "en": "Climbing gym {name}", - "ja": "クライミングジム{name}", - "fr": "Salle d’escalade {name}", - "it": "Palestra di arrampicata {name}" - } - } - ] - }, - "description": { - "de": "Eine Kletterhalle", - "en": "A climbing gym", - "ja": "クライミングジム", - "nl": "Een klimzaal", - "fr": "Une salle d’escalade", - "it": "Una palestra di arrampicata", - "ru": "Комплекс скалолазания" - }, - "tagRenderings": [ - "images", - { - "render": { - "en": "{name}", - "nl": "{name}", - "de": "{name}", - "ca": "{name}", - "fr": "{name}", - "id": "{name}", - "ru": "{name}", - "ja": "{name}", - "it": "{name}" - }, - "question": { - "en": "What is the name of this climbing gym?", - "nl": "Wat is de naam van dit Klimzaal?", - "de": "Wie heißt diese Kletterhalle?", - "ja": "このクライミングジムは何という名前ですか?", - "fr": "Quel est le nom de la salle d’escalade ?", - "it": "Qual è il nome di questa palestra di arrampicata?" - }, - "freeform": { - "key": "name" - }, - "id": "name" - }, - "website", - "phone", - "email", - "opening_hours" - ], - "mapRendering": [ - { - "icon": { - "render": "./assets/themes/climbing/climbing_gym.svg" - }, - "iconBadges": [ - { - "if": "opening_hours~*", - "then": "isOpen" - } - ], - "iconSize": { - "render": "40,40,center" - }, - "location": [ - "point", - "centroid" - ], - "label": { - "mappings": [ - { - "if": "name~*", - "then": "
    {name}
    " - } - ] - } - } - ] - }, - { - "id": "climbing_route", - "name": { - "en": "Climbing routes", - "de": "Kletterrouten", - "nl": "Klimroute", - "ja": "登坂ルート", - "nb_NO": "Klatreruter", - "fr": "Voies d’escalade", - "it": "Vie di arrampicata" - }, - "minzoom": 18, - "source": { - "osmTags": { - "and": [ - "climbing=route" - ] - } - }, - "title": { - "render": { - "de": "Kleterroute", - "en": "Climbing route", - "nl": "Klimroute", - "ja": "登坂ルート", - "nb_NO": "Klatrerute", - "it": "Via di arrampicata", - "fr": "Voie d’escalade" - }, - "mappings": [ - { - "if": "name~*", - "then": { - "de": "Kleterroute {name}", - "en": "Climbing route {name}", - "nl": "Klimroute {name}", - "ja": "登坂ルート{name}", - "it": "Via di arrampicata {name}", - "fr": "Voie d’escalade {name}" - } - } - ] - }, - "tagRenderings": [ - "images", - { - "render": { - "en": "{name}", - "nl": "{name}", - "de": "{name}", - "ca": "{name}", - "fr": "{name}", - "id": "{name}", - "ru": "{name}", - "ja": "{name}", - "it": "{name}", - "nb_NO": "{name}" - }, - "question": { - "en": "What is the name of this climbing route?", - "de": "Wie heißt diese Kletterroute?", - "nl": "Hoe heet deze klimroute?", - "ja": "この登坂ルートの名前は何ですか?", - "it": "Come si chiama questa via di arrampicata?", - "fr": "Quel est le nom de cette voie d’escalade ?", - "nb_NO": "Hva er navnet på denne klatreruten?" - }, - "freeform": { - "key": "name" - }, - "mappings": [ - { - "if": { - "and": [ - "noname=yes", - "name=" - ] - }, - "then": { - "en": "This climbing route doesn't have a name", - "de": "Diese Kletterroute hat keinen Namen", - "nl": "Deze klimroute heeft geen naam", - "ja": "この登坂ルートには名前がありません", - "it": "Questa via di arrampicata non ha un nome", - "fr": "Cette voie n’a pas de nom", - "nb_NO": "Denne klatreruten har ikke noe navn" - } - } - ], - "id": "Name" - }, - { - "question": { - "en": "How long is this climbing route (in meters)?", - "nl": "Hoe lang is deze klimroute (in meters)?", - "it": "Quanto è lunga questa via di arrampicata (in metri)?", - "fr": "Quelle est la longueur de cette voie (en mètres) ?", - "de": "Wie lang ist diese Kletterroute (in Metern)?", - "nb_NO": "Hvor mange meter er klatreruten?" - }, - "render": { - "de": "Diese Route ist {canonical(climbing:length)} lang", - "en": "This route is {canonical(climbing:length)} long", - "nl": "Deze klimroute is {canonical(climbing:length)} lang", - "ja": "このルート長は、 {canonical(climbing:length)} メーターです", - "nb_NO": "Denne ruten er {canonical(climbing:length)} lang", - "it": "Questo percorso è lungo {canonical(climbing:length)}", - "fr": "Cette voie fait {canonical(climbing:length)} de long" - }, - "freeform": { - "key": "climbing:length", - "type": "pnat" - }, - "id": "Length" - }, - { - "question": { - "en": "What is the grade of this climbing route according to the french/belgian system?", - "nl": "Hoe moeilijk is deze klimroute volgens het Franse/Belgische systeem?", - "it": "Qual è la difficoltà di questa via di arrampicata nel sistema francese/belga?", - "fr": "Quelle est la difficulté de cette voie selon le système franco-belge ?", - "de": "Wie hoch ist der Schwierigkeitsgrad dieser Kletterroute nach dem französisch/belgischen System?" - }, - "render": { - "de": "Die Schwierigkeit ist {climbing:grade:french} entsprechend des französisch/belgischen Systems", - "en": "The grade is {climbing:grade:french} according to the french/belgian system", - "nl": "De klimmoeilijkheid is {climbing:grade:french} volgens het Franse/Belgische systeem", - "ja": "フランス/ベルギーのランク評価システムによると、{climbing:grade:french}の困難度です", - "it": "Il grado di difficoltà è {climbing:grade:french} nel sistema francese/belga", - "fr": "Selon le système franco-belge, la difficulté de cette voie est de {climbing:grade:french}" - }, - "freeform": { - "key": "climbing:grade:french" - }, - "id": "Difficulty" - }, - { - "question": { - "en": "How many bolts does this route have before reaching the anchor?", - "fr": "Combien de prises cette voie possède avant d’atteindre la moulinette ?", - "de": "Wie viele Haken gibt es auf dieser Kletterroute bevor der Umlenker bzw. Standhaken erreicht ist?", - "it": "Quanti bulloni sono presenti in questo percorso prima di arrivare alla moulinette?" - }, - "render": { - "en": "This route has {climbing:bolts} bolts", - "fr": "Cette voie a {climbing:bolts} prises", - "de": "Diese Kletterroute hat {climbing:bolts} Haken", - "it": "Questo percorso ha {climbing:bolts} bulloni" - }, - "freeform": { - "key": "climbing:bolts", - "type": "pnat", - "addExtraTag": [ - "climbing:bolted=yes" - ] - }, - "mappings": [ - { - "if": "climbing:bolted=no", - "then": { - "en": "This route is not bolted", - "fr": "Cette voie n’a pas de prises", - "de": "Auf dieser Kletterroute sind keine Haken vorhanden", - "it": "In questo percorso non sono presenti bulloni" - }, - "hideInAnswer": true - }, - { - "if": "climbing:bolted=no&climbing:bolts=", - "then": { - "en": "This route is not bolted", - "fr": "Cette voie n’a pas de prises", - "de": "Auf dieser Kletterroute sind keine Haken vorhanden", - "it": "In questo percorso non sono presenti bulloni" - } - } - ], - "id": "Bolts" - }, - { - "question": "Is there other relevant info?", - "render": "

    Description


    {description}", - "freeform": { - "key": "description" - }, - "id": "Description" - }, - { - "render": { - "en": "The rock type is {_embedding_features_with_rock:rock} as stated on the surrounding crag", - "fr": "Le type de roche est {_embedding_features_with_rock:rock} selon le mur", - "it": "Il tipo di roccia è {_embedding_features_with_rock:rock} come dichiarato sul muro circostante", - "de": "Der Gesteinstyp ist {_embedding_features_with_rock:rock}, wie auf dem umgebenden Felsen angegeben" - }, - "freeform": { - "key": "_embedding_features_with_rock:rock" - }, - "id": "Rock type" - } - ], - "presets": [ - { - "title": { - "en": "a climbing route", - "nl": "een klimroute", - "fr": "une voie d’escalade", - "de": "eine kletterroute", - "it": "una via di arrampicata" - }, - "tags": [ - "sport=climbing", - "climbing=route" - ] - } - ], - "mapRendering": [ - { - "icon": { - "render": "circle:white;./assets/themes/climbing/climbing_route.svg" - }, - "iconSize": { - "render": "28,28,center" - }, - "location": [ - "point", - "centroid" - ], - "label": { - "mappings": [ - { - "if": "name~*", - "then": "
    {name}
    " - } - ] - } - }, - { - "color": { - "render": "#0f0" - }, - "width": { - "render": "4" - } - } - ] - }, - { - "id": "climbing", - "name": { - "nl": "Klimgelegenheden", - "de": "Klettermöglichkeiten", - "en": "Climbing opportunities", - "ja": "登坂教室", - "fr": "Opportunité d’escalade", - "it": "Opportunità di arrampicata" - }, - "minzoom": 10, - "source": { - "osmTags": { - "and": [ - "sport=climbing", - "climbing!~route", - "leisure!~sports_centre", - "climbing!=route_top", - "climbing!=route_bottom" - ] - } - }, - "title": { - "render": { - "en": "Climbing opportunity", - "nl": "Klimgelegenheid", - "de": "Klettermöglichkeit", - "ja": "登坂教室", - "nb_NO": "Klatremulighet", - "fr": "Opportunité d’escalade", - "it": "Opportunità di arrampicata" - }, - "mappings": [ - { - "if": "climbing=crag", - "then": { - "en": "Climbing crag {name}", - "fr": "Mur d’escalade {name}", - "it": "Muro da arrampicata {name}", - "de": "Klettergarten {name}" - } - }, - { - "if": { - "and": [ - { - "or": [ - "climbing=area", - "climbing=site" - ] - }, - "name~*" - ] - }, - "then": { - "en": "Climbing area {name}", - "nl": "Klimsite {name}", - "fr": "Zone d’escalade {name}", - "de": "Klettergebiet {name}", - "it": "Area di arrampicata {name}" - } - }, - { - "if": { - "or": [ - "climbing=site", - "climbing=area" - ] - }, - "then": { - "en": "Climbing site", - "nl": "Klimsite", - "fr": "Site d’escalade", - "de": "Klettergebiet", - "it": "Sito di arrampicata" - } - }, - { - "if": "name~*", - "then": { - "nl": "Klimgelegenheid {name}", - "en": "Climbing opportunity {name}", - "fr": "Opportunité d’escalade {name}", - "de": "Klettermöglichkeit {name}", - "it": "Opportunità di arrampicata {name}" - } - } - ] - }, - "description": { - "nl": "Een klimgelegenheid", - "de": "Eine Klettergelegenheit", - "en": "A climbing opportunity", - "ja": "登坂教室", - "nb_NO": "En klatremulighet", - "fr": "Opportunité d’escalade", - "it": "Un’opportunità di arrampicata" - }, - "tagRenderings": [ - "images", - { - "id": "minimap", - "render": "{minimap(18, id, _contained_climbing_route_ids): height: 9rem; overflow: hidden; border-radius:3rem; }" - }, - { - "render": { - "en": "

    Length overview

    {histogram(_length_hist)}", - "fr": "

    Résumé de longueur

    {histogram(_length_hist)}", - "de": "

    Längenübersicht

    {histogram(_length_hist)}", - "it": "

    Riassunto della lunghezza

    {histogram(_length_hist)}" - }, - "condition": "_length_hist!~\\[\\]", - "id": "Contained routes length hist" - }, - { - "render": { - "en": "

    Grades overview

    {histogram(_difficulty_hist)}", - "fr": "

    Résumé des difficultés

    {histogram(_difficulty_hist)}", - "de": "

    Schwierigkeitsübersicht

    {histogram(_difficulty_hist)}", - "it": "

    Riassunto delle difficoltà

    {histogram(_difficulty_hist)}" - }, - "condition": "_difficulty_hist!~\\[\\]", - "id": "Contained routes hist" - }, - { - "render": { - "en": "

    Contains {_contained_climbing_routes_count} routes

      {_contained_climbing_routes}
    ", - "fr": "

    Contient {_contained_climbing_routes_count} voies

      {_contained_climbing_routes}
    ", - "it": "

    Contiene {_contained_climbing_routes_count} vie

      {_contained_climbing_routes}
    ", - "de": "

    Enthält {_contained_climbing_routes_count} Routen

      {_contained_climbing_routes}
    " - }, - "condition": "_contained_climbing_routes~*", - "id": "Contained_climbing_routes" - }, - { - "render": { - "en": "{name}", - "nl": "{name}", - "de": "{name}", - "ca": "{name}", - "fr": "{name}", - "id": "{name}", - "ru": "{name}", - "ja": "{name}", - "it": "{name}" - }, - "question": { - "en": "What is the name of this climbing opportunity?", - "nl": "Wat is de naam van dit Klimgelegenheid?", - "de": "Wie heißt diese Klettergelegenheit?", - "ja": "この登坂教室の名前は何ですか?", - "fr": "Quel est le nom de ce site ?", - "it": "Qual è il nome di questa opportunità di arrampicata?" - }, - "freeform": { - "key": "name" - }, - "mappings": [ - { - "if": { - "and": [ - "noname=yes", - "name=" - ] - }, - "then": { - "en": "This climbing opportunity doesn't have a name", - "nl": "Dit Klimgelegenheid heeft geen naam", - "de": "Diese Klettergelegenheit hat keinen Namen", - "ja": "この登坂教室には名前がついていない", - "fr": "Ce site n’a pas de nom", - "it": "Questa opportunità di arrampicata non ha un nome" - } - } - ], - "id": "name" - }, - { - "question": "What kind of climbing opportunity is this?", - "mappings": [ - { - "if": "climbing=boulder", - "then": { - "en": "A climbing boulder - a single rock or cliff with one or a few climbing routes which can be climbed safely without rope", - "fr": "Rocher d’escalade, rocher avec une ou peu de voie permettant d’escalader sans corde", - "de": "Ein Kletterfelsen - ein einzelner Felsen oder eine Klippe mit einer oder wenigen Kletterrouten, die ohne Seil sicher bestiegen werden können", - "it": "Un masso per arrampicata (una singola roccia o falesia con una o poche vie di arrampicata che possono essere scalate in sicurezza senza una corda)" - } - }, - { - "if": "climbing=crag", - "then": { - "en": "A climbing crag - a single rock or cliff with at least a few climbing routes", - "fr": "Mur d’escalade, rocher avec plusieurs voies d’escalades", - "it": "Un muro da arrampicata (un singolo masso o falesia con almeno qualche via per arrampicata)", - "de": "Ein Kletterfelsen - ein einzelner Fels oder eine Klippe mit mindestens einigen Kletterrouten" - } - }, - { - "if": "climbing=area", - "then": "A climbing area with one or more climbing crags and/or boulders" - } - ], - "id": "Type" - }, - { - "question": { - "en": "What is the rock type here?", - "fr": "Quel est le type de roche ?", - "de": "Welchen Gesteinstyp gibt es hier?", - "it": "Qual è il tipo di roccia qua?" - }, - "render": { - "en": "The rock type is {rock}", - "fr": "La roche est du {rock}", - "de": "Der Gesteinstyp ist {rock}", - "it": "Il tipo di roccia è {rock}" - }, - "freeform": { - "key": "rock" - }, - "mappings": [ - { - "if": "rock=limestone", - "then": { - "en": "Limestone", - "nl": "Kalksteen", - "fr": "Calcaire", - "de": "Kalkstein", - "it": "Calcare" - } - } - ], - "condition": { - "or": [ - "climbing=crag", - "natural=cliff", - "natural=bare_rock" - ] - }, - "id": "Rock type (crag/rock/cliff only)" - } - ], - "presets": [ - { - "tags": [ - "sport=climbing" - ], - "title": { - "en": "a climbing opportunity", - "nl": "een klimgelegenheid", - "de": "eine klettermöglichkeit", - "ja": "登坂教室", - "nb_NO": "en klatremulighet", - "fr": "une opportunité d’escalade", - "it": "una opportunità di arrampicata" - }, - "description": { - "nl": "Een klimgelegenheid", - "de": "Eine Klettergelegenheit", - "en": "A climbing opportunity", - "ja": "登坂教室", - "nb_NO": "En klatremulighet", - "fr": "Opportunité d’escalade", - "it": "Un’opportunità di arrampicata" - } - } - ], - "calculatedTags": [ - "_contained_climbing_routes_properties=feat.overlapWith('climbing_route').map(f => f.feat.properties).map(p => {return {id: p.id, name: p.name, 'climbing:grade:french': p['climbing:grade:french'], 'climbing:length': p['climbing:length']} })", - "_contained_climbing_routes=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => `
  • ${p.name ?? 'climbing route'} (${p['climbing:grade:french'] ?? 'unknown difficulty'}, ${p['climbing:length'] ?? 'unkown length'} meter)
  • `).join('')", - "_contained_climbing_route_ids=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p.id)", - "_difficulty_hist=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p['climbing:grade:french'])", - "_length_hist=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p['climbing:length'])", - "_contained_climbing_routes_count=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').length" - ], - "mapRendering": [ - { - "icon": { - "render": "./assets/themes/climbing/climbing_no_rope.svg" - }, - "iconSize": { - "render": "40,40,center" - }, - "location": [ - "point", - "centroid" - ] - }, - { - "color": { - "render": "#d38d5fAA" - }, - "width": { - "render": "8" - } - } - ] - }, - { - "id": "maybe_climbing", - "name": { - "nl": "Klimgelegenheiden?", - "de": "Klettermöglichkeiten?", - "en": "Climbing opportunities?", - "ja": "登坂教室?", - "nb_NO": "Klatremuligheter?", - "fr": "Opportunités d’escalade ?", - "it": "Opportunità di arrampicata?" - }, - "minzoom": 19, - "source": { - "osmTags": { - "and": [ - { - "or": [ - "leisure=sports_centre", - "barrier=wall", - "barrier=retaining_wall", - "natural=cliff", - "natural=rock", - "natural=stone" - ] - }, - "climbing=" - ] - } - }, - "title": { - "render": { - "en": "Climbing opportunity?", - "nl": "Klimgelegenheid?", - "de": "Klettermöglichkeit?", - "ja": "登坂教室?", - "nb_NO": "Klatremulighet?", - "fr": "Opportunité d’escalade ?", - "it": "Opportunità di arrampicata?" - } - }, - "description": { - "nl": "Een klimgelegenheid?", - "de": "Eine Klettergelegenheit?", - "en": "A climbing opportunity?", - "ja": "登坂教室?", - "nb_NO": "En klatremulighet?", - "fr": "Opportunité d’escalade ?", - "it": "Un’opportunità di arrampicata?" - }, - "tagRenderings": [ - { - "id": "climbing-opportunity-name", - "render": { - "en": "{name}", - "de": "{name}", - "ca": "{name}", - "fr": "{name}", - "id": "{name}", - "ru": "{name}", - "ja": "{name}", - "nl": "{name}", - "it": "{name}" - }, - "condition": "name~*" - }, - { - "id": "climbing-possible", - "question": { - "en": "Is climbing possible here?", - "de": "Kann hier geklettert werden?", - "ja": "ここで登坂はできますか?", - "nb_NO": "Er klatring mulig her?", - "fr": "Est-il possible d’escalader ici ?", - "it": "È possibile arrampicarsi qua?" - }, - "mappings": [ - { - "if": { - "and": [ - "sport=climbing" - ] - }, - "then": { - "en": "Climbing is possible here", - "de": "Hier kann geklettert werden", - "ja": "ここでは登ることができる", - "nb_NO": "Klatring er mulig her", - "nl": "Klimmen is hier niet toegelaten", - "fr": "Escalader est possible", - "it": "È possibile arrampicarsi qua" - } - }, - { - "if": "climbing=no", - "then": { - "en": "Climbing is not possible here", - "de": "Hier kann nicht geklettert werden", - "ja": "ここでは登ることができない", - "nb_NO": "Klatring er ikke mulig her", - "nl": "Klimmen is hier niet toegelaten", - "fr": "Escalader n’est pas possible", - "it": "Non è possibile arrampicarsi qua" - } - }, - { - "if": { - "and": [ - "sport!~climbing" - ] - }, - "then": { - "en": "Climbing is not possible here", - "de": "Hier kann nicht geklettert werden", - "ja": "ここでは登ることができない", - "nb_NO": "Klatring er ikke mulig her", - "nl": "Klimmen is hier niet mogelijk", - "fr": "Escalader n’est pas possible", - "it": "Non è possibile arrampicarsi qua" - }, - "hideInAnswer": true - } - ] - } - ], - "mapRendering": [ - { - "icon": "./assets/themes/climbing/climbing_unknown.svg", - "location": [ - "point", - "centroid" - ] - }, - { - "color": { - "render": "#ddff55AA" - }, - "width": { - "render": "2" - } - } - ] - } + "climbing_club", + "climbing_gym", + "climbing_route", + "climbing", + "climbing_opportunity" ], "overrideAll": { -"allowMove":{"improveAccuracy": true}, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuracy": true + }, "+titleIcons": [ { "render": "
    {climbing:length}m
    ", @@ -1113,7 +132,8 @@ "de": " Meter", "eo": " metro", "it": " metri", - "ru": " метр" + "ru": " метр", + "ca": " metre" }, "default": true }, @@ -1129,7 +149,8 @@ "fr": " pieds", "de": " Fuß", "eo": " futo", - "it": " piedi" + "it": " piedi", + "ca": " peus" } } ] @@ -1242,7 +263,8 @@ "en": "Only customers", "fr": "Réservé aux clients", "de": "Nur für Kunden", - "it": "Riservato ai clienti" + "it": "Riservato ai clienti", + "ca": "Només clients" } }, { @@ -1252,7 +274,8 @@ "ru": "Только членам клуба", "fr": "Réservé aux membres", "de": "Nur für Vereinsmitglieder", - "it": "Riservato ai membri del club" + "it": "Riservato ai membri del club", + "ca": "Només membres del club" } }, { @@ -1547,7 +570,8 @@ "ru": "Здесь можно заняться спортивным скалолазанием", "ja": "ここでスポーツクライミングができます", "it": "L’arrampicata sportiva è possibile qua", - "hu": "Itt lehetőség van sportmászásra" + "hu": "Itt lehetőség van sportmászásra", + "fr": "De l’escalade est possible ici" } }, { @@ -1559,7 +583,8 @@ "ru": "Спортивное скалолазание здесь невозможно", "ja": "ここではスポーツクライミングはできません", "it": "L’arrampicata sportiva non è possibile qua", - "hu": "Itt nincs lehetőség sportmászásra" + "hu": "Itt nincs lehetőség sportmászásra", + "fr": "L’escalade est impossible ici" } }, { @@ -1702,4 +727,4 @@ "reviews" ] } -} +} \ No newline at end of file diff --git a/assets/themes/cycle_highways/cycle_highways.json b/assets/themes/cycle_highways/cycle_highways.json index a1d403c38..bd11a2854 100644 --- a/assets/themes/cycle_highways/cycle_highways.json +++ b/assets/themes/cycle_highways/cycle_highways.json @@ -3,7 +3,9 @@ "title": { "en": "Cycle highways", "de": "Radschnellwege", - "it": "Strade per velocipedi" + "it": "Strade per velocipedi", + "ca": "Vies ciclistes", + "fr": "Aménagements cyclables" }, "hideFromOverview": true, "maintainer": "L'imaginaire", @@ -13,7 +15,8 @@ "description": { "en": "This map shows cycle highways", "de": "Diese Karte zeigt Radschnellwege", - "it": "Questa cartina mostra le strade per velocipedi" + "it": "Questa cartina mostra le strade per velocipedi", + "fr": "Cette carte affiche les aménagements cyclables" }, "version": "2021-08-23", "startLat": 51.1599, @@ -99,7 +102,9 @@ ], "name": { "en": "cycle highways", - "de": "Radschnellwege" + "de": "Radschnellwege", + "ca": "vies ciclistes", + "fr": "Aménagements cyclables" }, "source": { "osmTags": "cycle_network=BE-VLG:cycle_highway" @@ -108,7 +113,9 @@ "title": { "render": { "en": "cycle highway", - "de": "Radschnellweg" + "de": "Radschnellweg", + "ca": "via ciclista", + "fr": "Aménagement cyclable" } }, "filter": [ diff --git a/assets/themes/cycle_infra/cycle_infra.json b/assets/themes/cycle_infra/cycle_infra.json index 98b1f0d92..7d358b37c 100644 --- a/assets/themes/cycle_infra/cycle_infra.json +++ b/assets/themes/cycle_infra/cycle_infra.json @@ -8,7 +8,8 @@ "nb_NO": "Sykkelinfrastruktur", "ru": "Велосипедная инфраструктура", "zh_Hant": "單車設施", - "hu": "Kerékpáros infrastruktúra" + "hu": "Kerékpáros infrastruktúra", + "ca": "Infraestructura per a bicicletes" }, "shortDescription": { "en": "A map where you can view and edit things related to the bicycle infrastructure.", @@ -25,7 +26,8 @@ "de": "Eine Karte zum Ansehen und Bearbeiten verschiedener Elementen der Fahrradinfrastruktur. Erstellt während #osoc21.", "it": "Una cartina dove vedere e modificare gli elementi riguardanti l’infrastruttura dei velocipedi. Realizzata durante #osoc21.", "zh_Hant": "可以檢視與編輯單車相關設施的地圖,在 #os0c21時製作。", - "hu": "Kerékpáros infrastruktúrával kapcsolatos dolgokat megjelenítő és szerkesztésre felkínáló térkép. Az #osoc21 (Open Summer of Code) alatt készült." + "hu": "Kerékpáros infrastruktúrával kapcsolatos dolgokat megjelenítő és szerkesztésre felkínáló térkép. Az #osoc21 (Open Summer of Code) alatt készült.", + "fr": "Une carte montrant les aménagements cyclables et où l’on peut rajouter des informations. Réalisée durant #osoc21." }, "maintainer": "MapComplete", "hideFromOverview": false, diff --git a/assets/themes/cyclenodes/cyclenodes.json b/assets/themes/cyclenodes/cyclenodes.json index 1d82601d2..7ff4392f0 100644 --- a/assets/themes/cyclenodes/cyclenodes.json +++ b/assets/themes/cyclenodes/cyclenodes.json @@ -91,7 +91,8 @@ "id": "node", "name": { "en": "nodes", - "de": "Knotenpunkte" + "de": "Knotenpunkte", + "ca": "nodes" }, "source": { "osmTags": { diff --git a/assets/themes/cyclestreets/cyclestreets.json b/assets/themes/cyclestreets/cyclestreets.json index 34fc29364..55efd9f8d 100644 --- a/assets/themes/cyclestreets/cyclestreets.json +++ b/assets/themes/cyclestreets/cyclestreets.json @@ -9,7 +9,8 @@ "de": "Fahrradstraßen", "it": "Strade ciclabili", "nb_NO": "Sykkelgater", - "hu": "Kerékpárosutcák" + "hu": "Kerékpárosutcák", + "ca": "Carrers ciclistes" }, "shortDescription": { "nl": "Een kaart met alle gekende fietsstraten", @@ -19,7 +20,8 @@ "nb_NO": "Et kart over sykkelveier", "de": "Eine Karte von Fahrradstraßen", "it": "Una cartina per le strade ciclabili", - "hu": "Kerékpárosutcák térképe" + "hu": "Kerékpárosutcák térképe", + "ca": "Un mapa de carrers ciclistes" }, "description": { "nl": "Een fietsstraat is een straat waar
    • automobilisten geen fietsers mogen inhalen
    • Er een maximumsnelheid van 30km/u geldt
    • Fietsers gemotoriseerde voertuigen links mogen inhalen
    • Fietsers nog steeds voorrang aan rechts moeten verlenen - ook aan auto's en voetgangers op het zebrapad


    Op deze open kaart kan je alle gekende fietsstraten zien en kan je ontbrekende fietsstraten aanduiden. Om de kaart aan te passen, moet je je aanmelden met OpenStreetMap en helemaal inzoomen tot straatniveau. ", @@ -52,7 +54,8 @@ "de": "Fahrradstraßen", "nb_NO": "Sykkelgater", "ru": "Cyclestreets", - "hu": "Kerékpárosutcák" + "hu": "Kerékpárosutcák", + "ca": "Carrers ciclistes" }, "minzoom": 7, "source": { @@ -106,7 +109,8 @@ "nb_NO": "Fremtidig sykkelvei", "it": "Futura strada ciclabile", "de": "Zukünftige Fahrradstraßen", - "hu": "Jövőbeli kerékpárosutca" + "hu": "Jövőbeli kerékpárosutca", + "ca": "Futur carrer ciclista" }, "description": { "nl": "Deze straat wordt binnenkort een fietsstraat", @@ -129,7 +133,8 @@ "nb_NO": "Fremtidig sykkelvei", "it": "Futura strada ciclabile", "de": "Zukünftige Fahrradstraße", - "hu": "Jövőbeli kerékpárosutca" + "hu": "Jövőbeli kerékpárosutca", + "ca": "Futur carrer ciclista" }, "mappings": [ { @@ -173,7 +178,8 @@ "ru": "Все улицы", "de": "Alle Straßen", "eo": "Ĉiuj stratoj", - "hu": "Minden utca" + "hu": "Minden utca", + "ca": "Tots els carrers" }, "description": { "nl": "Laag waar je een straat als fietsstraat kan markeren", @@ -204,7 +210,8 @@ "de": "Straße", "eo": "Strato", "nb_NO": "Gate", - "hu": "Utca" + "hu": "Utca", + "ca": "Carrer" }, "mappings": [ { diff --git a/assets/themes/drinking_water/drinking_water.json b/assets/themes/drinking_water/drinking_water.json index 838348fa6..e0f8800a3 100644 --- a/assets/themes/drinking_water/drinking_water.json +++ b/assets/themes/drinking_water/drinking_water.json @@ -10,7 +10,8 @@ "it": "Acqua potabile", "de": "Trinkwasserstellen", "nb_NO": "Drikkevann", - "hu": "Ivóvíz" + "hu": "Ivóvíz", + "ca": "Aigua potable" }, "description": { "en": "On this map, publicly accessible drinking water spots are shown and can be easily added", diff --git a/assets/themes/entrances/entrances.json b/assets/themes/entrances/entrances.json index abfb17820..dd472aef7 100644 --- a/assets/themes/entrances/entrances.json +++ b/assets/themes/entrances/entrances.json @@ -5,7 +5,8 @@ "zh_Hant": "出入口", "hu": "Épületek bejáratai", "de": "Eingänge", - "nl": "Toegangsdeuren" + "nl": "Toegangsdeuren", + "ca": "Entrades" }, "icon": "./assets/layers/entrance/door.svg", "description": { diff --git a/assets/themes/etymology/etymology.json b/assets/themes/etymology/etymology.json index eb672747c..8ca30bb8b 100644 --- a/assets/themes/etymology/etymology.json +++ b/assets/themes/etymology/etymology.json @@ -8,7 +8,8 @@ "ru": "Открытая этимологическая карта", "zh_Hant": "開放詞源地圖", "hu": "Etimológiai térkép", - "fr": "Open Etymology Map" + "fr": "Open Etymology Map", + "ca": "Open Etymology Map" }, "shortDescription": { "en": "What is the origin of a toponym?", diff --git a/assets/themes/facadegardens/facadegardens.json b/assets/themes/facadegardens/facadegardens.json index a626ac7d1..8b7cd0e2d 100644 --- a/assets/themes/facadegardens/facadegardens.json +++ b/assets/themes/facadegardens/facadegardens.json @@ -8,7 +8,8 @@ "it": "Giardini verticali", "fr": "Facade gardens", "de": "Fassadengärten", - "hu": "Homlokzati kertek" + "hu": "Homlokzati kertek", + "ca": "Jardins verticals" }, "shortDescription": { "nl": "Deze kaart toont geveltuintjes met foto's en bruikbare info over oriëntatie, zonlicht en planttypes.", @@ -47,7 +48,8 @@ "fr": "Jardins muraux", "de": "Fassadengärten", "it": "Giardini verticali", - "hu": "Homlokzati kertek" + "hu": "Homlokzati kertek", + "ca": "Jardins verticals" }, "minzoom": 12, "source": { @@ -67,7 +69,8 @@ "fr": "Jardin mural", "de": "Fassadengarten", "it": "Giardino verticale", - "hu": "Homlokzati kert" + "hu": "Homlokzati kert", + "ca": "Jardí vertical" } }, "description": { @@ -78,7 +81,8 @@ "fr": "Jardins muraux", "de": "Fassadengärten", "it": "Giardini verticali", - "hu": "Homlokzati kertek" + "hu": "Homlokzati kertek", + "ca": "Jardins verticals" }, "tagRenderings": [ "images", @@ -400,7 +404,8 @@ "it": "una giardino verticale", "fr": "une jardin mural", "de": "eine fassadengarten", - "hu": "homlokzatkert" + "hu": "homlokzatkert", + "ca": "un jardí vertical" }, "description": { "nl": "Voeg geveltuintje toe", @@ -409,7 +414,8 @@ "it": "Aggiungi un giardino verticale", "fr": "Ajouter un jardin mural", "de": "Einen Fassadengarten hinzufügen", - "hu": "Homlokzatkert hozzáadása" + "hu": "Homlokzatkert hozzáadása", + "ca": "Afegeix un jardí vertical" } } ], diff --git a/assets/themes/food/food.json b/assets/themes/food/food.json index cb72f22c3..bf37c8580 100644 --- a/assets/themes/food/food.json +++ b/assets/themes/food/food.json @@ -7,12 +7,13 @@ "it": "Ristoranti e fast food", "nb_NO": "Restauranter og søppelmat", "zh_Hant": "餐廳與快餐店", - "hu": "Éttermek és büfék" + "hu": "Éttermek és büfék", + "ca": "Restaurants i menjar ràpid" }, "description": { "nl": "Restaurants en fast food", "en": "Restaurants and fast food", - "de": "Restaurants und Fast Food" + "de": "Restaurants und Schnellimbisse" }, "maintainer": "", "icon": "./assets/layers/food/restaurant.svg", diff --git a/assets/themes/fritures/fritures.json b/assets/themes/fritures/fritures.json index 9e55aa9f7..5eb7b7f46 100644 --- a/assets/themes/fritures/fritures.json +++ b/assets/themes/fritures/fritures.json @@ -4,7 +4,8 @@ "nl": "Friturenkaart", "en": "Fries shops", "fr": "Carte des friteries", - "de": "Pommes-frites-Läden" + "de": "Pommes-frites-Läden", + "ca": "Botigues de patates" }, "description": { "en": "On this map, you'll find your favourite fries shop!", @@ -29,7 +30,8 @@ "fr": "Friteries", "de": "Pommesbude", "it": "Friggitoria", - "hu": "Sültkrumplievő-hely" + "hu": "Sültkrumplievő-hely", + "ca": "Botigues de patates" }, "=presets": [], "source": { diff --git a/assets/themes/ghostbikes/ghostbikes.json b/assets/themes/ghostbikes/ghostbikes.json index 09f48b015..c1bbdf883 100644 --- a/assets/themes/ghostbikes/ghostbikes.json +++ b/assets/themes/ghostbikes/ghostbikes.json @@ -24,7 +24,7 @@ "description": { "en": "A ghost bike 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.

    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 Witte Fiets of Spookfiets 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.

    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 Geisterrad ist ein weißes Fahrrad, dass zum Gedenken eines tödlich verunglückten Radfahrers vor Ort aufgestellt wurde.

    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.", + "de": "Ein Geisterrad ist ein weißes Fahrrad, dass zum Gedenken eines tödlich verunglückten Radfahrers vor Ort aufgestellt wurde.

    Auf dieser Karte sehen Sie alle Geisterräder, die in OpenStreetMap eingetragen sind. Fehlt ein Geisterrad? Jeder kann hier Informationen hinzufügen oder aktualisieren - Sie benötigen nur ein (kostenloses) OpenStreetMap-Konto.", "ja": "ゴーストバイクは、交通事故で死亡したサイクリストを記念するもので、事故現場の近くに恒久的に置かれた白い自転車の形をしています。

    このマップには、OpenStreetMapで知られているゴーストバイクがすべて表示されます。ゴーストバイクは行方不明ですか?誰でもここで情報の追加や更新ができます。必要なのは(無料の)OpenStreetMapアカウントだけです。", "zh_Hant": "幽靈單車是用來紀念死於交通事故的單車騎士,在事發地點附近放置白色單車。

    在這份地圖上面,你可以看到所有在開放街圖已知的幽靈單車。有缺漏的幽靈單車嗎?所有人都可以在這邊新增或是更新資訊-只有你有(免費)開放街圖帳號。", "fr": "Les vélos fantômes sont des mémoriaux pour les cyclistes tuées sur la route, prenant la forme de vélos blancs placés à proximité des faits.

    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).", diff --git a/assets/themes/grb_import/grb.json b/assets/themes/grb_import/grb.json index 35a95434a..b8abc0759 100644 --- a/assets/themes/grb_import/grb.json +++ b/assets/themes/grb_import/grb.json @@ -469,7 +469,7 @@ "_overlaps_with=feat.get('_overlaps_with_buildings').find(f => f.overlap > 1 /* square meter */ )", "_osm_obj:source:ref=feat.get('_overlaps_with')?.feat?.properties['source:geometry:ref']", "_osm_obj:id=feat.get('_overlaps_with')?.feat?.properties?.id", - "_osm_obj:source:date=feat.get('_overlaps_with')?.feat?.properties['source:geometry:date'].replace(/\\//g, '-')", + "_osm_obj:source:date=(feat.get('_overlaps_with')?.feat?.properties ?? {})['source:geometry:date']?.replace(/\\//g, '-')", "_osm_obj:building=feat.get('_overlaps_with')?.feat?.properties?.building", "_osm_obj:addr:street=(feat.get('_overlaps_with')?.feat?.properties ?? {})['addr:street']", "_osm_obj:addr:housenumber=(feat.get('_overlaps_with')?.feat?.properties ?? {})['addr:housenumber']", @@ -494,7 +494,8 @@ "#": "Failsafe", "if": "_grb_ref=", "then": { - "en": "Did not yet calculate the metatags... Reopen this popup" + "en": "Did not yet calculate the metatags... Reopen this popup", + "de": "Metatags noch nicht berechnet... Dieses Fenster erneut öffnen" } }, { diff --git a/assets/themes/hackerspaces/hackerspaces.json b/assets/themes/hackerspaces/hackerspaces.json index 23bbb15d6..0bc66064f 100644 --- a/assets/themes/hackerspaces/hackerspaces.json +++ b/assets/themes/hackerspaces/hackerspaces.json @@ -31,260 +31,6 @@ "startZoom": 1, "widenFactor": 5, "layers": [ - { - "id": "hackerspaces", - "name": { - "en": "Hackerspace", - "de": "Hackerspaces", - "ru": "Хакерспейс", - "zh_Hant": "駭客空間", - "hu": "Hackerspace" - }, - "minzoom": 8, - "title": { - "render": { - "en": "Hackerspace", - "de": "Hackerspace", - "ru": "Хакерспейс", - "zh_Hant": "駭客空間", - "hu": "Hackerspace" - }, - "mappings": [ - { - "if": { - "and": [ - "name~*" - ] - }, - "then": { - "en": " {name}", - "de": " {name}", - "ru": " {name}", - "zh_Hant": " {name}", - "hu": " {name}" - } - } - ] - }, - "description": { - "en": "Hackerspace", - "de": "Hackerspace", - "ru": "Хакерспейс", - "zh_Hant": "駭客空間", - "hu": "Hackerspace" - }, - "tagRenderings": [ - { - "id": "is_makerspace", - "question": { - "en": "Is this a hackerspace or a makerspace?", - "de": "Ist dies ein Hackerspace oder ein Makerspace?", - "zh_Hant": "這邊是駭客空間還是創客空間?", - "hu": "Ez hackerspace vagy makerspace?" - }, - "mappings": [ - { - "if": "hackerspace=makerspace", - "then": { - "en": "This is a makerspace", - "de": "Dies ist ein Makerspace", - "zh_Hant": "這是創客空間", - "hu": "Ez egy makerspace" - } - }, - { - "if": "hackerspace=", - "then": { - "en": "This is a traditional (software oriented) hackerspace", - "de": "Dies ist ein traditioneller (softwareorientierter) Hackerspace", - "zh_Hant": "這是傳統的 (軟體導向) 駭客空間", - "hu": "Ez egy hagyományos (szoftverekkel foglalkozó) hackerspace" - } - } - ] - }, - { - "question": { - "en": "What is the name of this hackerspace?", - "de": "Wie lautet der Name dieses Hackerspace?", - "zh_Hant": "這個駭客空間的名稱是?" - }, - "render": { - "en": "This hackerspace is named {name}", - "de": "Dieser Hackerspace heißt {name}", - "zh_Hant": "這個駭客空間叫 {name}" - }, - "freeform": { - "key": "name" - }, - "id": "hackerspaces-name" - }, - "website", - "email", - "phone", - { - "question": { - "en": "When is this hackerspace opened?", - "de": "Wann hat dieser Hackerspace geöffnet?", - "zh_Hant": "這個駭客空間的營業時間?" - }, - "freeform": { - "key": "opening_hours", - "type": "opening_hours" - }, - "render": { - "en": "{opening_hours_table()}", - "de": "{opening_hours_table()}", - "ru": "{opening_hours_table()}", - "zh_Hant": "{opening_hours_table()}" - }, - "mappings": [ - { - "if": { - "and": [ - "opening_hours=24/7" - ] - }, - "then": { - "en": "Opened 24/7", - "de": "durchgehend geöffnet", - "ru": "Открыто 24/7", - "zh_Hant": "24/7 營業" - } - } - ], - "id": "hackerspaces-opening_hours" - }, - "wheelchair-access", - { - "id": "hs-club-mate", - "question": { - "en": "Does this hackerspace serve Club Mate?", - "de": "Gibt es in diesem Hackerspace Club Mate?", - "zh_Hant": "這個駭客空間是否服務俱樂部伙伴?" - }, - "mappings": [ - { - "if": { - "and": [ - "drink:club-mate=yes" - ] - }, - "then": { - "en": "This hackerspace serves club mate", - "de": "In diesem Hackerspace gibt es Club Mate", - "zh_Hant": "這個駭客空間服務俱樂部伙伴" - } - }, - { - "if": { - "and": [ - "drink:club-mate=no" - ] - }, - "then": { - "en": "This hackerspace does not serve club mate", - "de": "In diesem Hackerspace gibt es kein Club Mate", - "zh_Hant": "這個駭客空間沒有服務俱樂部伙伴" - } - } - ] - }, - { - "render": { - "en": "This hackerspace was founded at {start_date}", - "de": "Dieser Hackerspace wurde gegründet am {start_date}", - "zh_Hant": "這駭客空間是 {start_date} 成立的" - }, - "question": { - "en": "When was this hackerspace founded?", - "de": "Wann wurde dieser Hackerspace gegründet?", - "zh_Hant": "這個駭客空間何時成立的?" - }, - "freeform": { - "key": "start_date", - "type": "date" - }, - "id": "hackerspaces-start_date" - } - ], - "presets": [ - { - "tags": [ - "leisure=hackerspace" - ], - "title": { - "en": "a hackerspace", - "de": "eine hackerspace", - "ru": "Хакерспейс", - "zh_Hant": "駭客空間", - "hu": "Hackerspace" - }, - "description": { - "en": "A hackerspace is an area where people interested in software gather", - "de": "Ein Hackerspace ist ein Ort, an dem sich Menschen treffen, die sich für Software interessieren", - "zh_Hant": "駭客空間是對軟體有興趣的人聚集的地方", - "hu": "A hackerspace egy olyan hely, ahol szoftverek iránt érdeklő emberek találkoznak" - } - }, - { - "tags": [ - "leisure=hackerspace", - "hackerspace=makerspace" - ], - "title": { - "en": "a makerspace", - "de": "eine makerspace", - "zh_Hant": "創客空間", - "hu": "Makerspace" - }, - "description": { - "en": "A makerspace is a place where DIY-enthusiasts gather to experiment with electronics such as arduino, LEDstrips, ...", - "de": "Ein Makerspace ist ein Ort, an dem Heimwerker-Enthusiasten zusammenkommen, um mit Elektronik zu experimentieren, wie Arduino, LED-Strips, ...", - "zh_Hant": "創客空間是 DIY 愛好者聚集在一起弄電子零件實驗,例如用 arduino、LEDstrips 等...", - "hu": "A makerspace olyan hely, ahol a barkácsolás szerelmesei találkoznak, hogy olyan elektronikai eszközökkel kísérletezzenek, mint például az Arduino vagy a LEDstrips." - } - } - ], - "source": { - "osmTags": { - "and": [ - "leisure=hackerspace" - ] - } - }, - "mapRendering": [ - { - "icon": { - "render": "./assets/themes/hackerspaces/glider.svg", - "mappings": [ - { - "if": { - "and": [ - "hackerspace=makerspace" - ] - }, - "then": "./assets/themes/hackerspaces/led.png" - } - ] - }, - "iconSize": { - "render": "40,40,center" - }, - "location": [ - "point", - "centroid" - ] - }, - { - "color": { - "render": "#00f" - }, - "width": { - "render": "8" - } - } - ] - } + "hackerspace" ] } \ No newline at end of file diff --git a/assets/themes/hailhydrant/hailhydrant.json b/assets/themes/hailhydrant/hailhydrant.json index 8d26b6315..6920c8d17 100644 --- a/assets/themes/hailhydrant/hailhydrant.json +++ b/assets/themes/hailhydrant/hailhydrant.json @@ -8,7 +8,7 @@ "fr": "Bornes incendies, extincteurs, casernes de pompiers et ambulanciers.", "it": "Idranti, estintori, caserme dei vigili del fuoco e stazioni delle ambulanze.", "nb_NO": "Hydranter, brannslukkere, brannstasjoner, og ambulansestasjoner.", - "de": "Hydranten, Feuerlöscher, Feuerwachen und Rettungswachen.", + "de": "Hydranten, Feuerlöscher, Feuerwachen und Rettungswachen", "hu": "Tűzcsapok, tűzoltó készülékek, tűzoltóságok és mentőállomások.", "nl": "Brandkranen, brandblussers, brandweerposten en ambulanceposten" }, diff --git a/assets/themes/mapcomplete-changes/mapcomplete-changes.json b/assets/themes/mapcomplete-changes/mapcomplete-changes.json index 4f2598a1a..c90abd4c4 100644 --- a/assets/themes/mapcomplete-changes/mapcomplete-changes.json +++ b/assets/themes/mapcomplete-changes/mapcomplete-changes.json @@ -1,16 +1,13 @@ { "id": "mapcomplete-changes", "title": { - "en": "Changes made with MapComplete", - "de": "Änderungen mit MapComplete" + "en": "Changes made with MapComplete" }, "shortDescription": { - "en": "Shows changes made by MapComplete", - "de": "Zeigt Änderungen von MapComplete" + "en": "Shows changes made by MapComplete" }, "description": { - "en": "This maps shows all the changes made with MapComplete", - "de": "Diese Karte zeigt alle Änderungen die mit MapComplete gemacht wurden" + "en": "This maps shows all the changes made with MapComplete" }, "maintainer": "", "icon": "./assets/svg/logo.svg", @@ -39,27 +36,23 @@ ], "title": { "render": { - "en": "Changeset for {theme}", - "de": "Änderungen für {theme}" + "en": "Changeset for {theme}" } }, "description": { - "en": "Shows all MapComplete changes", - "de": "Zeigt alle MapComplete Änderungen" + "en": "Shows all MapComplete changes" }, "tagRenderings": [ { "id": "render_id", "render": { - "en": "Changeset {id}", - "de": "Änderung {id}" + "en": "Changeset {id}" } }, { "id": "contributor", "render": { - "en": "Change made by {_last_edit:contributor}", - "de": "Änderung wurde von {_last_edit:contributor} gemacht" + "en": "Change made by {_last_edit:contributor}" } }, { @@ -335,8 +328,7 @@ } ], "question": { - "en": "Themename contains {search}", - "de": "Themenname enthält {search}" + "en": "Themename contains {search}" } } ] @@ -352,8 +344,7 @@ } ], "question": { - "en": "Made by contributor {search}", - "de": "Erstellt von {search}" + "en": "Made by contributor {search}" } } ] @@ -369,8 +360,7 @@ } ], "question": { - "en": "Not made by contributor {search}", - "de": "Nicht erstellt von {search}" + "en": "Not made by contributor {search}" } } ] @@ -385,8 +375,7 @@ { "id": "link_to_more", "render": { - "en": "More statistics can be found here", - "de": "Weitere Statistiken finden Sie hier" + "en": "More statistics can be found here" } }, { diff --git a/assets/themes/maps/maps.json b/assets/themes/maps/maps.json index cc91b08b5..15b1e50f4 100644 --- a/assets/themes/maps/maps.json +++ b/assets/themes/maps/maps.json @@ -10,7 +10,8 @@ "de": "Eine Karte der Karten", "eo": "Mapo de mapoj", "it": "Una mappa di mappe", - "nb_NO": "Et kart over kart" + "nb_NO": "Et kart over kart", + "ca": "Un mapa de mapes" }, "shortDescription": { "en": "This theme shows all (touristic) maps that OpenStreetMap knows of", diff --git a/assets/themes/maxspeed/licenses.json b/assets/themes/maxspeed/license_info.json similarity index 99% rename from assets/themes/maxspeed/licenses.json rename to assets/themes/maxspeed/license_info.json index bfa58bcc3..a712dc2b6 100644 --- a/assets/themes/maxspeed/licenses.json +++ b/assets/themes/maxspeed/license_info.json @@ -149,4 +149,4 @@ "https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg" ] } -] +] \ No newline at end of file diff --git a/assets/themes/maxspeed/maxspeed.json b/assets/themes/maxspeed/maxspeed.json index f8889202d..b89b59d16 100644 --- a/assets/themes/maxspeed/maxspeed.json +++ b/assets/themes/maxspeed/maxspeed.json @@ -155,7 +155,7 @@ }, "location": [ "point", - "centroid" + "projected_centerpoint" ] }, { @@ -224,4 +224,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/assets/themes/maxspeed/maxspeed_logo.svg b/assets/themes/maxspeed/maxspeed_logo.svg index 90da471c4..b8476bace 100644 --- a/assets/themes/maxspeed/maxspeed_logo.svg +++ b/assets/themes/maxspeed/maxspeed_logo.svg @@ -1,23 +1,47 @@ - - - - - - - + + + + + + diff --git a/assets/themes/nature/nature.json b/assets/themes/nature/nature.json index 59b6b8783..7605a6458 100644 --- a/assets/themes/nature/nature.json +++ b/assets/themes/nature/nature.json @@ -3,7 +3,8 @@ "title": { "en": "Into nature", "nl": "De Natuur in", - "de": "In die Natur" + "de": "In die Natur", + "ca": "A la natura" }, "shortDescription": { "en": "A map for nature lovers, with interesting POI's", diff --git a/assets/themes/notes/notes.json b/assets/themes/notes/notes.json index 6d30fbd15..34be3c74c 100644 --- a/assets/themes/notes/notes.json +++ b/assets/themes/notes/notes.json @@ -8,14 +8,15 @@ "en": "Notes on OpenStreetMap", "hu": "Jegyzetek az OpenStreetMapen", "nl": "Kaartnotas op OpenStreetMap", - "de": "Notizen von OpenStreetMap" + "de": "Notizen von OpenStreetMap", + "ca": "Notes a OpenStreetMap" }, "version": "0.1", "description": { "en": "A note is a pin on the map with some text to indicate something wrong.

    Make sure to checkout the filter view to search for users and text.", "hu": "A jegyzet egy gombostű a térképen egy szöveggel, amely azt jelzi, hogy valami nem stimmel.

    Felhasználók vagy szövegek kereséséhez nézd meg a szűrő nézetet.", "nl": "Een kaartnota bevat tekst op een specifieke locatie om aan te duiden dat er iets mis is of ontbreekt.

    Bekijk ook het filtermenu om de notas te filteren op tekst, gebruiker, datum, ...", - "de": "Ein Hinweis ist eine Stecknadel auf der Karte mit einer Fehlerbeschreibung.

    Über die Filteransicht kann nach Benutzern und Text gesucht werden." + "de": "Eine Notiz ist eine Stecknadel auf der Karte mit einer Fehlerbeschreibung.

    Über die Filteransicht kann nach Benutzer und Text gesucht werden." }, "icon": "./assets/themes/notes/logo.svg", "clustering": false, diff --git a/assets/themes/observation_towers/observation_towers.json b/assets/themes/observation_towers/observation_towers.json index fd5e756ea..e1c9b9420 100644 --- a/assets/themes/observation_towers/observation_towers.json +++ b/assets/themes/observation_towers/observation_towers.json @@ -7,7 +7,8 @@ "it": "Torri di osservazione", "ru": "Смотровые башни", "zh_Hant": "觀景塔", - "hu": "Kilátótornyok" + "hu": "Kilátótornyok", + "ca": "Torres d'observació" }, "shortDescription": { "en": "Publicly accessible towers to enjoy the view", diff --git a/assets/themes/openwindpowermap/openwindpowermap.json b/assets/themes/openwindpowermap/openwindpowermap.json index 13da81bc6..f19f16b18 100644 --- a/assets/themes/openwindpowermap/openwindpowermap.json +++ b/assets/themes/openwindpowermap/openwindpowermap.json @@ -9,7 +9,8 @@ "zh_Hant": "開放風力地圖", "id": "OpenWindPowerMap", "hu": "OpenWindPowerMap", - "nl": "Windmolens" + "nl": "Windmolens", + "ca": "OpenWindPowerMap" }, "maintainer": "Seppe Santens", "icon": "./assets/themes/openwindpowermap/logo.svg", @@ -29,317 +30,7 @@ "maxZoom": 8 }, "layers": [ - { - "id": "windturbine", - "name": { - "en": "wind turbine", - "nl": "windturbine", - "fr": "Éolienne", - "de": "Windräder", - "it": "pala eolica", - "zh_Hant": "風機", - "hu": "Szélerőmű" - }, - "source": { - "osmTags": "generator:source=wind" - }, - "minzoom": 10, - "title": { - "render": { - "en": "wind turbine", - "nl": "windturbine", - "fr": "éolienne", - "de": "Windrad", - "it": "pala eolica", - "zh_Hant": "風機", - "id": "turbin angin", - "hu": "szélerőmű" - }, - "mappings": [ - { - "if": "name~*", - "then": { - "en": "{name}", - "fr": "{name}", - "eo": "{name}", - "it": "{name}", - "ru": "{name}", - "zh_Hant": "{name}", - "id": "{name}", - "de": "{name}" - } - } - ] - }, - "tagRenderings": [ - { - "id": "turbine-output", - "render": { - "en": "The power output of this wind turbine is {generator:output:electricity}.", - "fr": "La puissance générée par cette éolienne est de {generator:output:electricity}.", - "it": "La potenza generata da questa pala eolica è {generator:output:electricity}.", - "zh_Hant": "這個風機的電力輸出是 {generator:output:electricity}。", - "id": "Output daya dari turbin angin ini adalah {generator:output:electricity}.", - "hu": "A szélerőmű teljesítménye: {generator:output:electricity}.", - "de": "Das Windrad erzeugt {generator:output:electricity} Strom." - }, - "question": { - "en": "What is the power output of this wind turbine? (e.g. 2.3 MW)", - "fr": "Quel est la puissance générée par cette éolienne ?", - "it": "Quant’è la potenza generata da questa pala eolica? (ad es. 2.3 MW)", - "zh_Hant": "這個風機的電力輸出是多少?(例如 2.3 MW)", - "id": "Berapa output daya dari turbin angin ini? (misalnya 2,3 MW)", - "hu": "Mekkora a teljesítménye ennek a szélturbinának? (pl. 2.3 MW)", - "de": "Wieviel Strom erzeugt das Windrad? (z.B. 2.3MW)" - }, - "freeform": { - "key": "generator:output:electricity", - "type": "pfloat" - } - }, - { - "id": "turbine-operator", - "render": { - "en": "This wind turbine is operated by {operator}.", - "fr": "Cette éolienne est opérée par {operator}.", - "it": "Questa pala eolica è gestita da {operator}.", - "zh_Hant": "這個風機營業商是 {operator}。", - "id": "Turbin angin ini dioperasikan oleh {operator}.", - "hu": "Ennek a szélerőműnek az üzemeltetője: {operator}.", - "de": "Die Windturbine wird betrieben von {operator}." - }, - "question": { - "en": "Who operates this wind turbine?", - "fr": "Qui est l’exploitant de cette éolienne ?", - "it": "Chi gestisce questa pala eolica?", - "zh_Hant": "這個風機營業商是?", - "hu": "Ki üzemelteti ezt a szélturbinát?", - "de": "Wer betreibt das Windrads?" - }, - "freeform": { - "key": "operator" - } - }, - { - "id": "turbine-height", - "render": { - "en": "The total height (including rotor radius) of this wind turbine is {height} metres.", - "fr": "La hauteur totale, incluant les pales, est de {height} mètres.", - "it": "L’altezza totale (raggio del rotore incluso) di questa pala eolica è di {height} metri.", - "zh_Hant": "這風機的總高度 (包括風葉直徑) 是 {height} 公尺。", - "hu": "A szélerőmű teljes (rotor sugarával együtt számított) magassága: {height} méter." - }, - "question": { - "en": "What is the total height of this wind turbine (including rotor radius), in metres?", - "fr": "Quelle est la hauteur totale de l’éolienne en mètres, pales incluses ?", - "it": "Qual è l’altezza (in metri e raggio del rotore incluso) di questa pala eolica?", - "zh_Hant": "這個風機的總高度是多少 (包括風葉大小) 公尺?", - "hu": "Hány méter a szélerőmű teljes magassága (a rotor sugarával együtt)?" - }, - "freeform": { - "key": "height", - "type": "pfloat" - } - }, - { - "id": "turbine-diameter", - "render": { - "en": "The rotor diameter of this wind turbine is {rotor:diameter} metres.", - "fr": "Le diamètre du rotor est de {rotor:diameter} mètres.", - "it": "Il diametro del rotore di questa pala eolica è di {rotor:diameter} metri.", - "zh_Hant": "這個風力渦輪機的風葉直徑是 {rotor:diameter} 公尺。", - "hu": "A szélturbina rotorátmérője: {rotor:diameter} méter.", - "de": "Der Rotordurchmesser der Windturbine ist {rotor:diameter} Meter." - }, - "question": { - "en": "What is the rotor diameter of this wind turbine, in metres?", - "fr": "Quel est le diamètre du rotor en mètres ?", - "it": "Qual è il diametro (in metri) del rotore di questa pala eolica?", - "zh_Hant": "這個風力渦輪機的風葉直徑是多少公尺?", - "hu": "Hány méter a rotorátmérője ennek a szélturbinának?", - "de": "Wie groß ist der Rotordurchmesser der Windturbine in Meter?" - }, - "freeform": { - "key": "rotor:diameter", - "type": "float" - } - }, - { - "id": "turbine-start-date", - "render": { - "en": "This wind turbine went into operation on/in {start_date}.", - "fr": "L’éolienne est active depuis {start_date}.", - "it": "Questa pala eolica è entrata in funzione in data {start_date}.", - "zh_Hant": "這個風機從 {start_date} 開始運轉。", - "id": "Turbin angin ini mulai beroperasi pada/dalam {start_date}.", - "hu": "A szélerőmű üzembe helyezése: {start_date}.", - "de": "Das Windrad wurde am {start_date} in Betrieb genommen." - }, - "question": { - "en": "When did this wind turbine go into operation?", - "fr": "Depuis quand l’éolienne est-elle en fonctionnement ?", - "it": "Quando è entrata in funzione questa pala eolica?", - "zh_Hant": "這個風機何時開始營運?", - "id": "Kapan turbin angin ini mulai beroperasi?", - "hu": "Mikor helyezték üzembe ezt a szélerőművet?", - "de": "Wann wurde das Windrad in Betrieb genommen?" - }, - "freeform": { - "key": "start_date", - "type": "date" - } - }, - "images" - ], - "presets": [ - { - "tags": [ - "power=generator", - "generator:source=wind" - ], - "title": { - "en": "a wind turbine", - "nl": "een windturbine", - "fr": "une éolienne", - "de": "ein Windrad", - "it": "una pala eolica", - "zh_Hant": "風機", - "hu": "Szélerőmű" - } - } - ], - "units": [ - { - "appliesToKey": [ - "generator:output:electricity" - ], - "applicableUnits": [ - { - "canonicalDenomination": "MW", - "alternativeDenomination": [ - "megawatts", - "megawatt" - ], - "human": { - "en": " megawatts", - "nl": " megawatt", - "fr": " megawatts", - "de": " Megawatt", - "eo": " megavatoj", - "it": " megawatt", - "ru": " мегаватт", - "zh_Hant": " 百萬瓦", - "id": " megawat", - "hu": " megawatt" - } - }, - { - "canonicalDenomination": "kW", - "alternativeDenomination": [ - "kilowatts", - "kilowatt" - ], - "human": { - "en": " kilowatts", - "nl": " kilowatt", - "fr": " kilowatts", - "de": " Kilowatt", - "eo": " kilovatoj", - "it": " kilowatt", - "nb_NO": " kilowatt", - "ru": " киловатт", - "zh_Hant": " 千瓦", - "id": " kilowat", - "hu": " kilowatt" - } - }, - { - "canonicalDenomination": "W", - "alternativeDenomination": [ - "watts", - "watt" - ], - "human": { - "en": " watts", - "nl": " watt", - "fr": " watts", - "de": " Watt", - "eo": " vatoj", - "it": " watt", - "ru": " ватт", - "zh_Hant": " 瓦", - "id": " watt", - "hu": " watt" - } - }, - { - "canonicalDenomination": "GW", - "alternativeDenomination": [ - "gigawatts", - "gigawatt" - ], - "human": { - "en": " gigawatts", - "nl": " gigawatt", - "fr": " gigawatts", - "de": " Gigawatt", - "eo": " gigavatoj", - "it": " gigawatt", - "ru": " гигаватт", - "zh_Hant": " 千兆瓦", - "id": " gigawatt", - "hu": " gigawatt" - } - } - ], - "eraseInvalidValues": true - }, - { - "appliesToKey": [ - "height", - "rotor:diameter" - ], - "applicableUnits": [ - { - "canonicalDenomination": "m", - "alternativeDenomination": [ - "meter" - ], - "human": { - "en": " meter", - "nl": " meter", - "fr": " mètres", - "de": " Meter", - "eo": " metro", - "it": " metri", - "ru": " метр", - "zh_Hant": " 公尺", - "id": " meter", - "hu": " méter" - } - } - ] - } - ], - "mapRendering": [ - { - "icon": "./assets/themes/openwindpowermap/wind_turbine.svg", - "label": { - "mappings": [ - { - "if": "generator:output:electricity~^[0-9]+.*[W]$", - "then": "
    {generator:output:electricity}
    " - } - ] - }, - "iconSize": "40, 40, bottom", - "location": [ - "point", - "centroid" - ] - } - ] - } + "windturbine" ], "defaultBackgroundId": "CartoDB.Voyager" } \ No newline at end of file diff --git a/assets/themes/parkings/parkings.json b/assets/themes/parkings/parkings.json index 0cc6ab693..b63d31e5b 100644 --- a/assets/themes/parkings/parkings.json +++ b/assets/themes/parkings/parkings.json @@ -9,7 +9,8 @@ "ru": "Парковка", "zh_Hant": "停車場", "id": "Tempat parkir", - "hu": "Parkolás" + "hu": "Parkolás", + "fr": "Stationnement" }, "shortDescription": { "nl": "Deze kaart toont verschillende parkeerplekken", @@ -28,7 +29,8 @@ "it": "Questa cartina mostra diversi posti dove parcheggiare", "zh_Hant": "這地圖顯示不同的停車空間", "id": "Peta ini menunjukkan tempat parkir yang berbeda", - "hu": "Ez a térkép különböző parkolókat jelenít meg" + "hu": "Ez a térkép különböző parkolókat jelenít meg", + "fr": "Cette carte affiche différents lieux de stationnement" }, "maintainer": "", "icon": "./assets/themes/parkings/parkings.svg", diff --git a/assets/themes/playgrounds/playgrounds.json b/assets/themes/playgrounds/playgrounds.json index 8ab906ae8..457ecfa55 100644 --- a/assets/themes/playgrounds/playgrounds.json +++ b/assets/themes/playgrounds/playgrounds.json @@ -7,11 +7,12 @@ "ja": "遊び場", "zh_Hant": "遊樂場", "ru": "Игровые площадки", - "de": "Spielpläzte", + "de": "Spielplätze", "it": "Parchi giochi", "nb_NO": "Lekeplasser", "id": "Taman bermain", - "hu": "Játszóterek" + "hu": "Játszóterek", + "ca": "Parcs infantils" }, "shortDescription": { "nl": "Een kaart met speeltuinen", @@ -24,7 +25,8 @@ "it": "Una cartina dei parchi giochi", "nb_NO": "Et kart med lekeplasser", "id": "Peta dengan taman bermain", - "hu": "Egy térkép játszóterekkel" + "hu": "Egy térkép játszóterekkel", + "ca": "Un mapa de parcs infantils" }, "description": { "nl": "Op deze kaart vind je speeltuinen en kan je zelf meer informatie en foto's toevoegen", diff --git a/assets/themes/postal_codes/postal_codes.json b/assets/themes/postal_codes/postal_codes.json index ac0ddfabf..00b67932f 100644 --- a/assets/themes/postal_codes/postal_codes.json +++ b/assets/themes/postal_codes/postal_codes.json @@ -4,19 +4,22 @@ "en": "Postal codes", "id": "Kode pos", "hu": "Irányítószámok", - "de": "Postleitzahlen" + "de": "Postleitzahlen", + "ca": "Codis postals" }, "shortDescription": { "en": "Postal codes", "id": "Kode pos", "hu": "Irányítószámok", - "de": "Postleitzahlen" + "de": "Postleitzahlen", + "ca": "Codis postals" }, "description": { "en": "Postal codes", "id": "Kode pos", "hu": "Irányítószámok", - "de": "Postleitzahlen" + "de": "Postleitzahlen", + "ca": "Codis postals" }, "maintainer": "", "icon": "./assets/themes/postal_codes/townhall.svg", @@ -35,7 +38,8 @@ "en": "postal codes", "id": "kode pos", "hu": "irányítószámok", - "de": "Postleitzahlen" + "de": "Postleitzahlen", + "ca": "codis postals" }, "minzoom": 8, "title": { @@ -53,7 +57,8 @@ "render": { "en": "The postal code is {postal_code}", "id": "Kode posnya adalah {postal_code}", - "hu": "Irányítószám: {postal_code}" + "hu": "Irányítószám: {postal_code}", + "de": "Die Postleitzahl lautet {postal_code}" } } ], @@ -123,7 +128,8 @@ "en": "town halls", "id": "balai kota", "hu": "polgármesteri hivatalok", - "de": "Rathäuser" + "de": "Rathäuser", + "ca": "ajuntaments" }, "minzoom": 12, "title": { diff --git a/assets/themes/postboxes/postboxes.json b/assets/themes/postboxes/postboxes.json index 88252bebd..8538e7a3d 100644 --- a/assets/themes/postboxes/postboxes.json +++ b/assets/themes/postboxes/postboxes.json @@ -45,7 +45,8 @@ "zh_Hant": "郵筒", "id": "Kotak pos", "hu": "Postaládák", - "nl": "Brievenbussen" + "nl": "Brievenbussen", + "ca": "Bústies" }, "minzoom": 12, "source": { @@ -59,7 +60,8 @@ "zh_Hant": "郵筒", "id": "Kotak pos", "hu": "Postaláda", - "nl": "Brievenbus" + "nl": "Brievenbus", + "ca": "Bústia" } }, "description": { @@ -89,7 +91,8 @@ "zh_Hant": "郵筒", "id": "kotak pos", "hu": "postaláda", - "nl": "een brievenbus" + "nl": "een brievenbus", + "ca": "una bústia" } } ], @@ -133,7 +136,8 @@ "zh_Hant": "郵局", "id": "Kantor pos", "hu": "Posták", - "nl": "Postkantoren" + "nl": "Postkantoren", + "ca": "Oficines de correus" }, "minzoom": 12, "source": { @@ -147,7 +151,8 @@ "zh_Hant": "郵局", "id": "Kantor Pos", "hu": "Posta", - "nl": "Postkantoor" + "nl": "Postkantoor", + "ca": "Oficina de correus" } }, "description": { @@ -181,7 +186,8 @@ "en": "What are the opening hours for this post office?", "zh_Hant": "這間郵局的開放時間是?", "id": "Jam berapa kantor pos ini buka?", - "hu": "Mikor van nyitva ez a posta?" + "hu": "Mikor van nyitva ez a posta?", + "de": "Wie sind die Öffnungszeiten dieser Poststelle?" }, "mappings": [ { @@ -210,7 +216,8 @@ "zh_Hant": "郵局", "id": "Kantor Pos", "hu": "Posta", - "nl": "een postkantoor" + "nl": "een postkantoor", + "ca": "una oficina de correus" } } ], @@ -225,7 +232,8 @@ "zh_Hant": "目前開放", "id": "Saat ini buka", "hu": "Most nyitva", - "nl": "Momenteel geopend" + "nl": "Momenteel geopend", + "ca": "Actualment obert" }, "osmTags": "_isOpen=yes" } diff --git a/assets/themes/shops/shops.json b/assets/themes/shops/shops.json index 7a70fee7f..7450ef251 100644 --- a/assets/themes/shops/shops.json +++ b/assets/themes/shops/shops.json @@ -10,7 +10,8 @@ "it": "Mappa dei negozi", "nb_NO": "Kart over åpne butikker", "hu": "Bolttérkép", - "nl": "Winkels" + "nl": "Winkels", + "ca": "Open Shop Map" }, "shortDescription": { "en": "An editable map with basic shop information", diff --git a/assets/themes/sidewalks/sidewalks.json b/assets/themes/sidewalks/sidewalks.json index fe1d9c22f..9bbb9cd56 100644 --- a/assets/themes/sidewalks/sidewalks.json +++ b/assets/themes/sidewalks/sidewalks.json @@ -4,14 +4,19 @@ "en": "Sidewalks", "ru": "Тротуары", "nl": "Voetpaden", - "de": "Gehwege" + "de": "Gehwege", + "ca": "Voreres" }, "shortDescription": { - "en": "Sidewalk mapping" + "en": "Sidewalk mapping", + "ca": "Mapejat de voreres", + "de": "Kartierung von Bürgersteigen" }, "description": { "en": "Experimental theme", - "ru": "Экспериментальная тема" + "ru": "Экспериментальная тема", + "ca": "Petició experimental", + "de": "Experimentelles Thema" }, "maintainer": "", "icon": "./assets/svg/bug.svg", @@ -27,7 +32,8 @@ "name": { "en": "Sidewalks", "ru": "Тротуары", - "de": "Gehweg" + "de": "Gehweg", + "ca": "Voreres" }, "minzoom": 12, "source": { @@ -44,7 +50,8 @@ "render": { "en": "{name}", "ru": "{name}", - "de": "{name}" + "de": "{name}", + "ca": "{name}" }, "mappings": [ { @@ -54,13 +61,15 @@ ] }, "description": { - "en": "Layer showing sidewalks of highways" + "en": "Layer showing sidewalks of highways", + "de": "Ebene mit Bürgersteigen" }, "tagRenderings": [ { "id": "streetname", "render": { - "en": "This street is named {name}" + "en": "This street is named {name}", + "de": "Diese Straße heißt {name}" } }, { diff --git a/assets/themes/sport_pitches/sport_pitches.json b/assets/themes/sport_pitches/sport_pitches.json index 0a607cf71..1e8428e75 100644 --- a/assets/themes/sport_pitches/sport_pitches.json +++ b/assets/themes/sport_pitches/sport_pitches.json @@ -9,7 +9,8 @@ "ru": "Спортивные площадки", "de": "Sportplätze", "it": "Campi sportivi", - "hu": "Sportpályák" + "hu": "Sportpályák", + "ca": "Camps d'esports" }, "shortDescription": { "nl": "Deze kaart toont sportvelden", diff --git a/assets/themes/street_lighting/street_lighting.json b/assets/themes/street_lighting/street_lighting.json index 711edc529..a510d9de5 100644 --- a/assets/themes/street_lighting/street_lighting.json +++ b/assets/themes/street_lighting/street_lighting.json @@ -8,7 +8,8 @@ "ru": "Уличное освещение", "zh_Hant": "道路照明", "hu": "Közvilágítás", - "de": "Straßenbeleuchtung" + "de": "Straßenbeleuchtung", + "ca": "Il·luminació als carrers" }, "description": { "en": "On this map you can find everything about street lighting", @@ -30,7 +31,8 @@ "nl": "Verlichte straten", "zh_Hant": "有照明的道路", "hu": "Kivilágított utcák", - "de": "Beleuchtete Straßen" + "de": "Beleuchtete Straßen", + "ca": "Il·luminació de carrers" }, "source": { "osmTags": { @@ -49,7 +51,8 @@ "nl": "Verlichte straat", "zh_Hant": "照明道路", "hu": "Kivilágított utca", - "de": "Bleuchtete Straße" + "de": "Bleuchtete Straße", + "ca": "Il·luminació del carrer" }, "mappings": [ { @@ -90,7 +93,8 @@ "en": "This street is not lit", "nl": "Deze straat is niet verlicht", "zh_Hant": "這個道路沒有照明", - "hu": "Ezen az utcán nincs közvilágítás" + "hu": "Ezen az utcán nincs közvilágítás", + "de": "Diese Straße ist nicht beleuchtet" } }, { @@ -99,7 +103,8 @@ "en": "This street is lit at night", "nl": "Deze straat is 's nachts verlicht", "zh_Hant": "這個道路晚上有照明", - "hu": "Ez az utca éjszaka ki van világítva" + "hu": "Ez az utca éjszaka ki van világítva", + "de": "Diese Straße ist nachts beleuchtet" }, "hideInAnswer": true }, @@ -109,7 +114,8 @@ "en": "This street is lit 24/7", "nl": "Deze straat is 24/7 verlicht", "zh_Hant": "這個道路 24/7 有照明", - "hu": "Ez az utca éjjel-nappal ki van világítva" + "hu": "Ez az utca éjjel-nappal ki van világítva", + "de": "Diese Straße ist durchgehend beleuchtet" } } ] @@ -125,7 +131,8 @@ "ru": "Все улицы", "zh_Hant": "所有道路", "hu": "Minden utca", - "de": "Alle Straßen" + "de": "Alle Straßen", + "ca": "Tots els carrers" }, "source": { "osmTags": { @@ -144,7 +151,8 @@ "ru": "Улица", "zh_Hant": "照明", "hu": "Utca", - "de": "Straße" + "de": "Straße", + "ca": "Carrer" }, "mappings": [ { @@ -193,7 +201,8 @@ "en": "This street is not lit", "nl": "Deze straat is niet verlicht", "zh_Hant": "這道路沒有照明", - "hu": "Ez az utca nincs kivilágítva" + "hu": "Ez az utca nincs kivilágítva", + "de": "Diese Straße ist nicht beleuchtet" } }, { @@ -202,7 +211,8 @@ "en": "This street is lit at night", "nl": "Deze straat is 's nachts verlicht", "zh_Hant": "這道路晚上有照明", - "hu": "Ez az utca éjjel ki van világítva" + "hu": "Ez az utca éjjel ki van világítva", + "de": "Diese Straße ist nachts beleuchtet" }, "hideInAnswer": true }, @@ -212,7 +222,8 @@ "en": "This street is lit 24/7", "nl": "Deze straat is 24/7 verlicht", "zh_Hant": "這道路 24/7 有照明", - "hu": "Ez az utca éjjel-nappal ki van világítva" + "hu": "Ez az utca éjjel-nappal ki van világítva", + "de": "Diese Straße ist durchgehend beleuchtet" } } ] diff --git a/assets/themes/surveillance/surveillance.json b/assets/themes/surveillance/surveillance.json index 4dea9d8db..b723e4e0f 100644 --- a/assets/themes/surveillance/surveillance.json +++ b/assets/themes/surveillance/surveillance.json @@ -8,7 +8,8 @@ "fr": "Surveillance", "de": "Überwachung unter Überwachung", "it": "Sorveglianza sotto controllo", - "hu": "Megfigyelt térfigyelés" + "hu": "Megfigyelt térfigyelés", + "ca": "Vigilància sota vigilància" }, "shortDescription": { "en": "Surveillance cameras and other means of surveillance", diff --git a/assets/themes/toilets/toilets.json b/assets/themes/toilets/toilets.json index 306af8c3f..7b0de72ba 100644 --- a/assets/themes/toilets/toilets.json +++ b/assets/themes/toilets/toilets.json @@ -11,7 +11,8 @@ "pl": "Mapa otwartych toalet", "it": "Mappa libera delle toilet", "nb_NO": "Åpent toalettkart", - "hu": "WC-térkép" + "hu": "WC-térkép", + "ca": "Open Toilet Map" }, "description": { "en": "A map of public toilets", diff --git a/assets/themes/trees/trees.json b/assets/themes/trees/trees.json index 31cabf0e7..910160fa5 100644 --- a/assets/themes/trees/trees.json +++ b/assets/themes/trees/trees.json @@ -12,7 +12,9 @@ "de": "Bäume", "nb_NO": "Trær", "id": "Pohon", - "hu": "Fatérkép" + "hu": "Fatérkép", + "ca": "Arbres", + "es": "Árboles" }, "shortDescription": { "nl": "Breng bomen in kaart", @@ -25,7 +27,9 @@ "pl": "Sporządzić mapę wszystkich drzew", "de": "Kartieren Sie alle Bäume", "nb_NO": "Kartlegg alle trærne", - "hu": "Az összes fa feltérképezése" + "hu": "Az összes fa feltérképezése", + "ca": "Mapeja tots els arbres", + "es": "Mapa de los Árboles" }, "description": { "nl": "Breng bomen in kaart!", @@ -37,7 +41,9 @@ "ru": "Нанесите все деревья на карту!", "de": "Kartieren Sie alle Bäume!", "nb_NO": "Kartlegg trærne.", - "hu": "Térképezzünk fel minden fát!" + "hu": "Térképezzünk fel minden fát!", + "ca": "Mapeja tots els arbres.", + "es": "Mapa de todos los Árboles" }, "maintainer": "Midgard", "icon": "./assets/themes/trees/logo.svg", diff --git a/assets/themes/waste/waste.json b/assets/themes/waste/waste.json index e0934a029..694546043 100644 --- a/assets/themes/waste/waste.json +++ b/assets/themes/waste/waste.json @@ -5,7 +5,8 @@ "title": { "en": "Waste", "nl": "Afval", - "de": "Abfall" + "de": "Abfall", + "ca": "Brossa" }, "description": { "en": "Map showing waste baskets and recycling facilities.", diff --git a/assets/themes/waste_basket/waste_basket.json b/assets/themes/waste_basket/waste_basket.json index d5d41b703..2c5d9f3f0 100644 --- a/assets/themes/waste_basket/waste_basket.json +++ b/assets/themes/waste_basket/waste_basket.json @@ -7,7 +7,8 @@ "it": "Cestino dei rifiuti", "zh_Hant": "垃圾筒", "hu": "Kukatérkép", - "id": "Keranjang Sampah" + "id": "Keranjang Sampah", + "ca": "Papepera" }, "shortDescription": { "en": "A map with waste baskets", diff --git a/assets/translators.json b/assets/translators.json index a2d077231..0bff98565 100644 --- a/assets/translators.json +++ b/assets/translators.json @@ -1,7 +1,7 @@ { "contributors": [ { - "commits": 106, + "commits": 115, "contributor": "Pieter Vander Vennet" }, { @@ -9,7 +9,7 @@ "contributor": "danieldegroot2" }, { - "commits": 47, + "commits": 58, "contributor": "kjon" }, { @@ -36,6 +36,14 @@ "commits": 21, "contributor": "Anonymous" }, + { + "commits": 16, + "contributor": "el_libre como el chaval" + }, + { + "commits": 16, + "contributor": "Robin van der Linde" + }, { "commits": 15, "contributor": "WaldiS" @@ -60,10 +68,6 @@ "commits": 10, "contributor": "Irina" }, - { - "commits": 10, - "contributor": "Robin van der Linde" - }, { "commits": 9, "contributor": "Jacque Fresco" @@ -72,6 +76,10 @@ "commits": 8, "contributor": "LeJun" }, + { + "commits": 7, + "contributor": "Win Olario" + }, { "commits": 6, "contributor": "Štefan Baebler" @@ -94,7 +102,7 @@ }, { "commits": 5, - "contributor": "el_libre como el chaval" + "contributor": "David Haberthür" }, { "commits": 5, @@ -128,10 +136,6 @@ "commits": 4, "contributor": "Polgár Sándor" }, - { - "commits": 4, - "contributor": "David Haberthür" - }, { "commits": 4, "contributor": "phlostically" @@ -180,6 +184,10 @@ "commits": 3, "contributor": "SiegbjornSitumeang" }, + { + "commits": 2, + "contributor": "paunofu" + }, { "commits": 2, "contributor": "Localizer" @@ -232,6 +240,10 @@ "commits": 2, "contributor": "Leo Alcaraz" }, + { + "commits": 1, + "contributor": "deep map" + }, { "commits": 1, "contributor": "HO Gin Wang" diff --git a/assets/welcome_message.json b/assets/welcome_message.json index 0d53ded19..31f736510 100644 --- a/assets/welcome_message.json +++ b/assets/welcome_message.json @@ -1,4 +1,15 @@ [ + { + "start_date": "2022-05-30", + "end_date":"2022-06-05", + "message": "The 3rd of June is World Bicycle DayX. Go find a bike shop or bike pump nearby", + "featured_theme": "cyclofix" + }, + { + "start_date": "2022-04-24", + "end_date": "2022-05-30", + "message": "Help translating MapComplete! If you have some free time, please translate MapComplete to your favourite language. Read the instructions here" + }, { "start_date": "2022-04-18", "end_date": "2022-04-24", diff --git a/langs/ca.json b/langs/ca.json index 3a89e8296..1e596ce6e 100644 --- a/langs/ca.json +++ b/langs/ca.json @@ -19,7 +19,7 @@ "loading": "Inspeccionant propietats per si aquest element pot ser esborrat.", "loginToDelete": "Has d'entrar per esborrar un punt", "notEnoughExperience": "Aquest punt l'ha fet una altra persona.", - "onlyEditedByLoggedInUser": "Aquest punt només pot ser editat per tu, el pots esborrar amb seguretat.", + "onlyEditedByLoggedInUser": "Aquest punt només l'has editat tu, el pots esborrar amb seguretat.", "partOfOthers": "Aquest punt és part d'una via o relació i no es pot esborrar directament.", "readMessages": "Tens missatges sense llegir. Llegeix això abans d'esborrar un punt - algú potser t'ha escrit", "reasons": { @@ -50,10 +50,11 @@ "hasBeenImported": "Aquest punt ja ha estat importat", "import": { "hasBeenImported": "Aquest objecte ha estat importat", + "howToTest": "Per provar, afegeix test=true o backend=osm-test a l'URL. El conjunt de canvis s'imprimirà a la consola. Obre un PR per oficialitzar aquesta petició per activar realment el botó d'importació.", "importTags": "L'element rebrà {tags}", - "zoomInMore": "Ampliar més per importar aquest element", "officialThemesOnly": "El botó d'importació està desactivat per a temes no oficials per evitar accidents", - "wrongType": "Aquest element no és un punt o una via i no pot ser importat" + "wrongType": "Aquest element no és un punt o una via i no pot ser importat", + "zoomInMore": "Ampliar més per importar aquest element" }, "importTags": "L'element rebrà {tags}", "intro": "Has marcat un lloc on no coneixem les dades.
    ", @@ -64,33 +65,33 @@ "stillLoading": "Les dades es segueixen carregant. Espera una mica abans d'afegir cap punt.", "title": "Vols afegir un punt?", "warnVisibleForEveryone": "La teva contribució serà vista per tothom", + "wrongType": "Aquest element no és un punt o una via i no pot ser importat", "zoomInFurther": "Apropa per afegir un punt.", - "zoomInMore": "Ampliar per importar aquest element", - "wrongType": "Aquest element no és un punt o una via i no pot ser importat" + "zoomInMore": "Ampliar per importar aquest element" }, "apply_button": { - "isApplied": "S'aplicaran els canvis", - "appliedOnAnotherObject": "L'objecte {id} rebrà {tags}" + "appliedOnAnotherObject": "L'objecte {id} rebrà {tags}", + "isApplied": "S'aplicaran els canvis" }, "attribution": { "attributionContent": "

    Totes les dades provenen d'OpenStreetMap, i es poden reutilitzar lliurement sota la Llicència Oberta de Base de Dades (ODbL).

    ", "attributionTitle": "Avís d’atribució", "codeContributionsBy": "MapComplete ha estat fet per {contributors} i {hiddenCount} més contribuïdors", "donate": "Donar suport econòmic a MapComplete", + "editId": "Obre l'editor en línia d'OpenStreetMap aquí", "editJosm": "Editar aquí amb JOSM", "iconAttribution": { "title": "Icones utilitzades" }, + "josmNotOpened": "No s'ha pogut contactar amb JOSM. Assegura't que estigui obert i que el control remot estigui habilitat", "josmOpened": "JOSM és obert", "mapContributionsBy": "Les dades mostrades tenen edicions fetes per {contributors}", "mapContributionsByAndHidden": "Les dades mostrades tenen edicions fetes per {contributors} i {hiddenCount} col·laboradors més", "openIssueTracker": "Registrar un error", "openMapillary": "Obrir Mapillary aquí", - "themeBy": "Tema mantingut per {author}", - "editId": "Obre l'editor en línia d'OpenStreetMap aquí", "openOsmcha": "Veure darreres edicions fetes amb {theme}", - "translatedBy": "MapComplete ha estat traduït per {contributors} i {hiddenCount} col·laboradors més", - "josmNotOpened": "No s'ha pogut contactar amb JOSM. Assegura't que estigui obert i que el control remot estigui habilitat" + "themeBy": "Tema mantingut per {author}", + "translatedBy": "MapComplete ha estat traduït per {contributors} i {hiddenCount} col·laboradors més" }, "back": "Tornar", "backToMapcomplete": "Tornar a l'explicació general de la petició", @@ -101,6 +102,8 @@ "download": { "downloadAsPdf": "Baixar un PDF del mapa actual", "downloadAsPdfHelper": "Ideal per imprimir el mapa actual", + "downloadAsSvg": "Baixa un SVG del mapa actual", + "downloadAsSvgHelper": "Compatible amb Inkscape o Adobe Illustrator; necessitaràs un processament ", "downloadCSV": "Baixar dades visibles com a CSV", "downloadCSVHelper": "Compatible amb LibreOffice Calc, Excel, …", "downloadFeatureAsGeojson": "Baixar com a arxiu GeoJson", @@ -108,15 +111,13 @@ "downloadGeoJsonHelper": "Compatible amb QGIS, ArcGIS, ESRI, …", "downloadGeojson": "Baixar dades visibles com a GeoJSON", "downloadGpx": "Baixar com a arxiu GPX", + "downloadGpxHelper": "Un fitxer GPX es pot utilitzar amb la majoria de dispositius i aplicacions de navegació", "exporting": "Exportant…", "includeMetaData": "Incloure metadades (darrer editor, valors calculats, ...)", "licenseInfo": "

    Avís de drets de còpia

    Les dades proveïdes estan sota ODbL. Es poden reutilitzar de forma gratuïta, però
    • l'atribució a © Contribuïdors d'OpenStreetMap és obligatòria
    • Qualsevol canvi ha de seguir la llicència
    Llegeix sencer l'avís de drets de còpia per més detalls.", "noDataLoaded": "No s'han carregat dades. La baixada estarà disponible aviat", "title": "Baixar dades visibles", - "uploadGpx": "Pujar la teva traça a OpenStreetMap", - "downloadAsSvg": "Baixa un SVG del mapa actual", - "downloadAsSvgHelper": "Compatible amb Inkscape o Adobe Illustrator; necessitaràs un processament ", - "downloadGpxHelper": "Un fitxer GPX es pot utilitzar amb la majoria de dispositius i aplicacions de navegació" + "uploadGpx": "Pujar la teva traça a OpenStreetMap" }, "example": "Exemple", "examples": "Exemples", @@ -190,6 +191,7 @@ "removeLocationHistory": "Esborrar l'historial d'ubicació", "returnToTheMap": "Tornar al mapa", "save": "Desar", + "screenToSmall": "Obrir {theme} en una finestra nova", "search": { "error": "Alguna cosa no ha sortit bé…", "nothing": "Res trobat…", @@ -250,14 +252,16 @@ }, "searchWikidata": "Cercar a Wikidata", "wikipediaboxTitle": "Viquipèdia" - }, - "screenToSmall": "Obrir {theme} en una finestra nova" + } }, "image": { "addPicture": "Afegir foto", "ccb": "sota la llicència CC-BY", + "ccbExplanation": "La llicència CC-BY implica que qualsevol persona pot utilitzar la teva imatge per a qualsevol propòsit, però t'ha d'atribuir", "ccbs": "sota llicència CC-BY-SA", + "ccbsExplanation": "La llicència CC-BY-SA implica que qualsevol persona pot utilitzar la teva imatge per a qualsevol propòsit, però t'ha d'atribuir i les modificacions de la imatge s'han de tornar a publicar sota la mateixa llicència", "cco": "en domini públic", + "ccoExplanation": "Afegir una imatge al domini públic implica que qualsevol pot fer qualsevol cosa amb la teva imatge", "doDelete": "Esborrar imatge", "dontDelete": "Cancel·lar", "isDeleted": "Esborrada", @@ -269,63 +273,68 @@ "uploadMultipleDone": "{count} imatges afegides. Gràcies per ajudar.", "uploadingMultiple": "Pujant {count} imatges…", "uploadingPicture": "Pujant la teva imatge…", - "willBePublished": "La teva foto serà publicada: ", - "ccoExplanation": "Afegir una imatge al domini públic implica que qualsevol pot fer qualsevol cosa amb la teva imatge", - "ccbExplanation": "La llicència CC-BY implica que qualsevol persona pot utilitzar la teva imatge per a qualsevol propòsit, però t'ha d'atribuir" + "willBePublished": "La teva foto serà publicada: " }, "importHelper": { - "inspectDidAutoDected": "La capa es va seleccionar automàticament", - "inspectLooksCorrect": "Aquests valors semblen correctes", + "introduction": { + "description": "L'ajudant d'importació converteix un conjunt de dades extern en notes. El conjunt de dades extern ha de coincidir amb una de les capes MapComplete existents. Per a cada article que introdueixes a l'importador, es crearà una nota única. Aquestes notes es mostraran juntament amb les característiques rellevants en aquests mapes per afegir-les fàcilment.", + "importFormat": "Un text d'una nota ha de tenir el format següent per poder ser recollit:
    [Una petita introducció]
    https://mapcomplete.osm.be /[themename].html?[paràmetres com ara lat i lon]#import
    [totes les etiquetes de la funció]
    " + }, + "login": { + "lockNotice": "Aquesta pàgina està bloquejada. Necessites {importHelperUnlock} conjunts de canvis per poder accedir aquí.", + "loggedInWith": "Actualment has entrat com a {name} i has fet {csCount} conjunts de canvis", + "loginIsCorrect": "{name} és el compte correcte per crear les notes d'importació.", + "loginRequired": "Has d'entrar per continuar", + "userAccountTitle": "Seleccionar compte d'usuari" + }, "mapPreview": { - "title": "Vista prèvia del mapa", - "selectLayer": "Amb quina capa coincideix aquesta importació?", + "autodetected": "La capa es va deduir automàticament en funció de les propietats", "confirm": "Les característiques es troben a la ubicació correcta del mapa", - "autodetected": "La capa es va deduir automàticament en funció de les propietats" + "mismatch": "{count} característiques no coincideixen amb la capa seleccionada. Assegura't que hi hagi les etiquetes per indicar el tipus, és a dir, {tags}", + "selectLayer": "Amb quina capa coincideix aquesta importació?", + "title": "Vista prèvia del mapa" + }, + "previewAttributes": { + "allAttributesSame": "Totes les funcions a importar tenen aquesta etiqueta", + "inspectDataTitle": "Inspecciona les dades de {count} funcions per importar", + "inspectLooksCorrect": "Aquests valors semblen correctes", + "someHaveSame": "{count} característiques per importar tenen aquesta etiqueta, això és un {percentage}% del total" }, "selectFile": { - "loadedFilesAre": "L'arxiu carregat actualment és {file}", - "noFilesLoaded": "No s'ha carregat cap arxiu", - "title": "Seleccionar arxiu", "description": "Seleccionar un fitxer .csv o .geojson per començar", - "fileFormatDescription": "Selecciona un fitxer .csv o un fitxer .geojson", - "errNoName": "Algunes columnes no tenen nom", "errDuplicate": "Algunes columnes tenen el mateix nom", "errNoLatOrLon": "La capçalera no conté `lat` o `lon`", + "errNoName": "Algunes columnes no tenen nom", "errNotFeatureCollection": "El fitxer JSON carregat no és una col·lecció de funcions geojson", - "errPointsOnly": "El fitxer JSON carregat només hauria de contenir punts" + "errPointsOnly": "El fitxer JSON carregat només hauria de contenir punts", + "fileFormatDescription": "Selecciona un fitxer .csv o un fitxer .geojson", + "fileFormatDescriptionCsv": "Al fitxer CSV, hi hauria d'haver una columna lat i lon amb les coordenades a WGS84. Hi hauria d'haver una columna addicional per a cada atribut.", + "fileFormatDescriptionGeoJson": "Al fitxer geojson només haurien d'estar presents els punts. Les propietats haurien de ser exactament aquelles propietats que haurien d'anar a OpenStreetMap", + "loadedFilesAre": "L'arxiu carregat actualment és {file}", + "noFilesLoaded": "No s'ha carregat cap arxiu", + "title": "Seleccionar arxiu" }, - "selectLayer": "Seleccionar capa...", - "title": "Ajuda de l'importador", - "userAccountTitle": "Seleccionar compte d'usuari", - "validateDataTitle": "Validar dades", - "inspectDataTitle": "Inspecciona les dades de {count} funcions per importar", - "loginRequired": "Has d'entrar per continuar", - "someHaveSame": "{count} característiques per importar tenen aquesta etiqueta, això és un {percentage}% del total", - "locked": "Necessites almenys {importHelperUnlock} per utilitzar l'ajudant d'importació", - "loggedInWith": "Actualment has entrat com a {name} i has fet {csCount} conjunts de canvis", - "lockNotice": "Aquesta pàgina està bloquejada. Necessites {importHelperUnlock} conjunts de canvis per poder accedir aquí.", - "allAttributesSame": "Totes les funcions a importar tenen aquesta etiqueta", - "loginIsCorrect": "{name} és el compte correcte per crear les notes d'importació." + "title": "Ajuda de l'importador" }, "importInspector": { "title": "Inspeccionar i controlar notes d'importació" }, "importLayer": { - "layerName": "Possible {title}", - "popupTitle": "Possible {title}", - "notFound": "No he pogut trobar {title}: esborra-ho", + "alreadyMapped": "Ja hi ha un altre {title} al mapa; aquest punt és un duplicat", "description": "Una capa que importa entrades per a {title}", - "importHandled": "
    Aquesta funció s'ha gestionat. Gràcies pel teu esforç.
    ", "importButton": "import_button({layerId}, _tags, he trobat un {title} aquí; afegeix-lo al mapa,./assets/svg/addSmall.svg,,,id)", - "alreadyMapped": "Ja hi ha un altre {title} al mapa; aquest punt és un duplicat" + "importHandled": "
    Aquesta funció s'ha gestionat. Gràcies pel teu esforç.
    ", + "layerName": "Possible {title}", + "notFound": "No he pogut trobar {title}: esborra-ho", + "popupTitle": "Possible {title}" }, "index": { "#": "Aquests textos es mostren sobre els botons de les peticions quan no hi ha petició carregada", "featuredThemeTitle": "Destacades aquesta setmana", "intro": "MapComplete és un visor i editor d'OpenStreetMap, que et mostra informació sobre elements d'una petició específica i et permet actualitzar-los.", + "logIn": "Entra per veure altres temes que has visitat anteriorment", "pickTheme": "Tria una petició de sota per començar.", - "title": "Benvingut/da a MapComplete", - "logIn": "Entra per veure altres temes que has visitat anteriorment" + "title": "Benvingut/da a MapComplete" }, "move": { "cancel": "Cancel·lar moviment", @@ -363,6 +372,7 @@ "anonymous": "Usuari/a anònim/a", "closeNote": "Tancar nota", "createNote": "Crear una nova nota", + "createNoteIntro": "Hi ha alguna cosa malament o falta al mapa? Creeu una nota aquí. Aquests seran verificats per voluntaris.", "createNoteTitle": "Crear una nova nota aquí", "disableAllNoteFilters": "Deshabilitar tots els filtres", "isClosed": "Aquesta nota s'ha resolt", @@ -370,109 +380,133 @@ "loginToAddComment": "Entrar per afegir un comentari", "loginToAddPicture": "Entrar per afegir una imatge", "loginToClose": "Entrar per tancar aquesta nota", + "noteIsPublic": "Això serà visible per a tothom", "noteLayerDoEnable": "Habilita la capa que mostra notes", + "noteLayerHasFilters": "Algunes notes poden estar ocultes per un filtre", + "noteLayerNotEnabled": "La capa que mostra les notes no està activada. Aquesta capa s'ha d'habilitar per afegir una nota nova", + "notesLayerMustBeEnabled": "La capa 'notes' està desactivada. Activa-la per afegir una nota", "reopenNote": "Reobrir nota", "reopenNoteAndComment": "Reobrir nota i comentar", "textNeeded": "Introdueix un text descriptiu per crear una nota", - "noteIsPublic": "Això serà visible per a tothom", - "warnAnonymous": "No has entrat. No podrem contactar amb tu per resoldre el problema.", - "noteLayerNotEnabled": "La capa que mostra les notes no està activada. Aquesta capa s'ha d'habilitar per afegir una nota nova", "typeText": "Escriu text per afegir un comentari", - "notesLayerMustBeEnabled": "La capa 'notes' està desactivada. Activa-la per afegir una nota", - "noteLayerHasFilters": "Algunes notes poden estar ocultes per un filtre", - "createNoteIntro": "Hi ha alguna cosa malament o falta al mapa? Creeu una nota aquí. Aquests seran verificats per voluntaris." + "warnAnonymous": "No has entrat. No podrem contactar amb tu per resoldre el problema." }, "privacy": { + "editing": "Quan facis un canvi al mapa, aquest canvi es registra a OpenStreetMap i està disponible públicament per a tothom. Un conjunt de canvis fet amb MapComplete inclou les dades següents:
    • Els canvis que has fet
    • El teu nom d'usuari
    • Quan es fa aquest canvi
    • La petició que vas utilitzar mentre feies el canvi
    • L'idioma de la interfície d'usuari
    • Una indicació de la proximitat a la que estaves dels objectes canviats. Altres mapejadors poden utilitzar aquesta informació per determinar si es va fer un canvi basant-se en una enquesta o en una investigació remota
    Consulta la política de privadesa a OpenStreetMap.org per obtenir informació detallada. Ens agradaria recordar-te que pots utilitzar un nom de ficció quan et registris.", "editingTitle": "Quan es facin canvis", + "geodata": "Quan MapComplete obté la geolocalització, aquesta i les ubicacions visitades anteriorment romandran al teu dispositiu. Les teves dades d'ubicació mai s'envien automàticament a cap altre lloc, tret que alguna funcionalitat indiqui clarament el contrari.", "geodataTitle": "La teva geoclocalització", + "intro": "La privadesa és important, tant per a l'individu com per a la societat. MapComplete intenta respectar la vostra privadesa tant com sigui possible, fins al punt que no es necessita cap banner de galetes molest. No obstant això, encara volem informar-vos quina informació es recopila i es comparteix, en quines circumstàncies i per què es fan aquestes compensacions.", + "miscCookies": "MapComplete s'integra amb diversos altres serveis, especialment per carregar imatges de característiques. Les imatges s'allotgen en diversos servidors de tercers, que poden establir galetes per si mateixos.", "miscCookiesTitle": "Altres galetes", + "surveillance": "Mentre llegeixes la política de privadesa, probablement t'interessa la privadesa, a nosaltres també! Fins i tot hem creat una petició que mostra les càmeres de vigilància. No dubtis a mapejar-les totes.", "title": "Política de privacitat", + "tracking": "Per obtenir informació sobre qui visita el nostre lloc web, es recopila informació tècnica. S'inclou el país des del qual has visitat la pàgina web, quin lloc web t'ha remès a MapComplete, el tipus de dispositiu i la mida de la pantalla. Es col·loca una galeta al teu dispositiu per indicar que has visitat MapComplete avui. Aquestes dades no són prou detallades per identificar-te personalment. Aquestes estadístiques només estan disponibles per a tothom en conjunt i estan disponibles públicament per a tothom", "trackingTitle": "Dades estadístiques", "whileYoureHere": "Et preocupa la privacitat?" }, "professional": { "aboutMc": { - "survey": { - "title": "Possibilitats d'enquesta" - }, - "title": "Utilitzar MapComplete a la teva organització", - "layers": { - "title": "Quines dades es poden mostrar amb MapComplete?" - }, "internalUse": { + "intro": "

    Un cop les dades estiguin a l'OpenStreetMap, probablement voldràs utilitzar-les també. El teu MapComplete pot tenir un còmode botó d'exportació, que t'ofereix la possibilitat de baixar les dades en molts formats oberts utilitzables a QGis, ArcGis, Excel, LibreOffice-calc,...

    Algú Així, amb habilitats bàsiques de full de càlcul, poden crear fàcilment gràfics i coneixements sobre les dades, mentre que els experts en GIS de la teva organització poden treballar fàcilment amb aquestes dades a la seva aplicació preferida.

    Si es necessita una configuració automatitzada, hi ha disponible una API d'ús lliure i gestionada per la comunitat.

    ", "title": "Ús de les dades en processos interns" }, - "text2": "Si encara no et sents segur, les possibilitats es descriuen a continuació. A més, es responen algunes preguntes habituals" + "layers": { + "intro": "

    MapComplete té un potent sistema de plantilles, que permet crear ràpidament un mapa que mostri precisament les característiques que necessitis i que mostri els atributs rellevants a les finestres emergents.

    Aquestes dades es poden obtenir des d'OpenStreetMap< /b> directament, però MapComplete també pot utilitzar conjunts de dades externs, p. per comparar OpenStreetMap amb un altre conjunt de dades o per mostrar dades que no són adequades per a OpenStreetMap (activitats planificades, estadístiques, ...)

    ", + "title": "Quines dades es poden mostrar amb MapComplete?" + }, + "survey": { + "intro": "

    MapComplete és una eina desondeig fàcil d'utilitzar. És ideal per recollir el necessari en pocs clics, tant a l'escriptori com al mòbil. Aquestes dades s'aporten directament a OpenStreetMap.

    Podem configurar una eina d'enquesta personalitzada, demanant-nos precisament les dades que necessitis.

    Tens un conjunt de dades que s'hagi de (re)actualitzar? Aquest és el moment perfecte per canviar a OpenStreetMap. MapComplete pot mostrar el teu conjunt de dades i OpenStreetMap alhora, facilitant la visita a totes les ubicacions i veure què ja s'ha aportat a la comunitat.

    \n", + "title": "Possibilitats d'enquesta" + }, + "text0": "Si hi ha una petició de MapComplete existent, no dubtis a utilitzar-la o inserir-la al lloc web. Incrustar les peticions públiques és gratuït i sempre ho serà.", + "text1": "Necessites altres dades, però la petició encara no existeix? Els desenvolupadors de MapComplete poden crear-lo per a tu amb un pressupost decent. Posa't en contacte amb el correu electrònic, github o envia un missatge a través de osm.org", + "text2": "Si encara no et sents segur, les possibilitats es descriuen a continuació. A més, es responen algunes preguntes habituals", + "title": "Utilitzar MapComplete a la teva organització" }, "aboutOsm": { "aboutOsm": { + "intro": "OpenStreetMap és una base de dades global compartida, creada per voluntaris. Totes les geodades es poden aportar a OpenStreetMap, sempre que es puguin verificar sobre el terreny.
    OpenStreetMap s'ha convertit en un conjunt de dades molt ampli i profund, ja que conté dades de milers de categories de objectes. Un objecte individual també pot tenir un munt d'atributs, aportant molts matisos, per exemple:", + "li0": "Els carrers tenen geometria, però també poden tenir informació sobre la velocitat màxima, la superfície, si estan il·luminats, el seu nom, un enllaç a la Viquipèdia, un enllaç al nom que reben, quines rutes de senderisme, bicicletes i autobús hi circulen, …", + "li1": "Les botigues i altres serveis poden tenir un horari d'obertura, un número de telèfon, un enllaç al lloc web, quines formes de pagament s'admeten, què venen, quins serveis ofereixen, …", + "li2": "Els lavabos poden tenir informació sobre l'accessibilitat per a cadira de rodes, un canviador, si cal pagar, …", "li3": "i molt, molt més…", - "title": "Què és OpenStreetMap?", - "li2": "Els lavabos poden tenir informació sobre l'accessibilitat per a cadira de rodes, un canviador, si cal pagar, …" + "title": "Què és OpenStreetMap?" }, "benefits": { - "title": "Beneficis de l'ecosistema OSM", + "intro": "Pot ser molt difícil deixar el teu propi conjunt de dades enrere, ja que la creació d'aquest conjunt de dades sovint necessitava molt de temps i esforç.
    No obstant això, els avantatges de canviar a OSM són enormes:", + "li0": "Ja no estàs sol per reunir i mantenir aquest conjunt de dades: tota una comunitat està al teu costat", + "li1": "Les teves dades arribaran a un públic més gran que mai a través de Bing Maps, Apple Maps, Facebook, Instagram, Pokemon Go, OsmAnd, Organic Maps, Maps.me, Mapbox, Komoot, gairebé totes les aplicacions de cicle, …", "li2": "Moltes organitzacions governamentals i municipis també utilitzen OpenStreetMap als seus llocs web", - "li0": "Ja no estàs sol per reunir i mantenir aquest conjunt de dades: tota una comunitat està al teu costat" + "title": "Beneficis de l'ecosistema OSM" }, "license": { - "title": "La llicència", + "intro": "OpenStreetMap té llicència sota la llicència de base de dades oberta. El text complet dels drets d'autor es pot resumir de la següent manera:", "li0": "Un producte que utilitza dades d'OpenStreetMap ha de donar-ne atribució.", - "outro": "La llicència té algunes implicacions; aquestes s'expliquen a continuació.", "li1": "Les dades d'OpenStreetMap han de romandre obertes. Això significa que les dades d'un mapa que conté dades d'OpenStreetMap es poden tornar a copiar.", - "intro": "OpenStreetMap té llicència sota la llicència de base de dades oberta. El text complet dels drets d'autor es pot resumir de la següent manera:" + "outro": "La llicència té algunes implicacions; aquestes s'expliquen a continuació.", + "title": "La llicència" }, "vandalism": { - "title": "Què és el vandalisme?", + "intro": "Com qualsevol persona pot editar les dades, és possible que es faci un canvi maliciós. Tanmateix, això és extremadament rar per alguns motius:", "li0": "la barrera tècnica per fer canvis és alta", + "li1": "un petit canvi maliciós té un impacte baix, per tant, poca recompensa per a un vàndal", "li2": "un canvi d'alt impacte es nota ràpidament i es reverteix ja que molta gent utilitza aquestes dades", "li3": "tots els canvis es fan un seguiment i es vincula a un sol usuari. Un delinqüent reincident és ràpidament prohibit", - "li1": "un petit canvi maliciós té un impacte baix, per tant, poca recompensa per a un vàndal", - "li4": "A Bèlgica (i alguns altres països), la primera edició d'un nou col·laborador es verifica i corregeix sistemàticament si cal." + "li4": "A Bèlgica (i alguns altres països), la primera edició d'un nou col·laborador es verifica i corregeix sistemàticament si cal.", + "title": "Què és el vandalisme?" } }, "drawbacks": { + "intro": "Tot i que unir-se a aquesta comunitat té enormes beneficis, hi ha alguns temes que cal tenir en compte.", "licenseNuances": { + "intro": "OpenStreetMap té llicència sota la llicència de base de dades oberta que estableix que:", + "li0": "Totes les dades es poden reutilitzar per a qualsevol finalitat, incloses les comercials", + "li1": "Les aplicacions o productes que utilitzen OpenStreetMap haurien de donar un avís clar de drets d'autor", + "li2": "Qualsevol conjunt de dades o producte que contingui dades d'OpenStreetMap també s'ha de tornar a publicar sota ODbL, incloses les modificacions d'aquest conjunt de dades i en un format utilitzable.", + "outro": "Això té algunes implicacions que s'han de tenir en compte per a alguns casos d'ús, tal com s'explica a continuació", + "title": "Implicacions de l'ODbL: alguns casos d'ús", "usecaseGatheringOpenData": { + "intro": "MapComplete és una excel·lent manera de crear dades obertes, també per als governs. Per defecte, aquestes dades seran redistribuïbles lliurement sota l'ODbL. No obstant això, si hi ha un requisit per publicar les dades recopilades sota una llicència de domini públic (on tots els drets es concedeixen al públic i no es requereix cap atribució), l'ODbL és massa restrictiu. En aquest cas, es pot demanar als col·laboradors que afegeixin dades com a domini públic (per exemple, informant-los en la petició de Mapcomplete).", "title": "Aconseguint dades obertes" }, "usecaseMapDifferentSources": { - "title": "Creació d'un mapa a partir de diferents fonts", + "intro": "

    Per exemple, es podria fer un mapa amb tots els bancs d'alguna ciutat, basant-se en els bancs coneguts per OpenStreetMap. Aquest mapa imprès necessita una declaració clara que les dades del mapa es basen en OpenStreetMap. La venda d'aquests mapes està permesa. Si el mapejador nota que falten els bancs en alguna zona i els afegeix al mapa imprès, les dades dels bancs que falten també s'obren automàticament. Això vol dir que un col·laborador d'OpenStreetMap pot agafar el mapa de paper i utilitzar-lo per tornar a afegir els bancs que falten a OpenStreetMap.

    Aquest col·laborador també té dret a demanar el conjunt de dades dels bancs que falten, que també s'ha de proporcionar.

    Si el mapejador nota que falten els bancs en alguna àrea i els afegeix al mapa imprès, les dades dels bancs que falten també s'obren automàticament. Això vol dir que un col·laborador d'OpenStreetMap pot agafar el mapa de paper i utilitzar-lo per tornar a afegir els bancs que falten a OpenStreetMap. Aquest col·laborador també té dret a demanar el conjunt de dades dels bancs que falten, que també s'han de proporcionar.

    Per descomptat, un mapa amb només bancs pot resultar avorrit. El creador de mapes també pot decidir afegir una capa amb botigues, possiblement procedent d'un altre proveïdor de geodades amb una altra llicència. Això està permès, si el mapa indica clarament que els bancs provenen d'OSM (amb ODBL) i les botigues tenen una font diferent (eventualment amb tots els drets reservats).

    No obstant això, barrejar dos conjunts de dades sense distinció no és permés. Per exemple, el mapejador podria trobar que OSM té dades excel·lents sobre bancs d'una part de la ciutat i el proveïdor de codi tancat podria tenir dades excel·lents sobre bancs d'una altra part de la ciutat, la fusió d'aquests conjunts de dades en un podria ser problemàtic:

    ", + "li0": "la llicència oberta requeriria que les modificacions es tornin a publicar obertament…", "li1": "… mentre que la llicència de tots els drets reservats ho prohibiria.", "outro": "Com a resultat, aquest tipus de barreja no està permès", - "li0": "la llicència oberta requeriria que les modificacions es tornin a publicar obertament…" - }, - "title": "Implicacions de l'ODbL: alguns casos d'ús", - "li1": "Les aplicacions o productes que utilitzen OpenStreetMap haurien de donar un avís clar de drets d'autor", - "li0": "Totes les dades es poden reutilitzar per a qualsevol finalitat, incloses les comercials", - "intro": "OpenStreetMap té llicència sota la llicència de base de dades oberta que estableix que:", - "outro": "Això té algunes implicacions que s'han de tenir en compte per a alguns casos d'ús, tal com s'explica a continuació" - }, - "unsuitedData": { - "title": "Les dades no són acceptables per OpenStreetMap", - "li1": "Els esdeveniments no es registren, ni tampoc les obres viàries que només duren uns quants dies." + "title": "Creació d'un mapa a partir de diferents fonts" + } }, "title": "Alguns inconvenients a tenir en compte", - "intro": "Tot i que unir-se a aquesta comunitat té enormes beneficis, hi ha alguns temes que cal tenir en compte." + "unsuitedData": { + "intro": "La regla bàsica d'OpenStreetMap és que totes les dades han de ser verificables sobre el terreny i són permanents. Això implica que algunes dades no es poden enviar directament a OpenStreetMap, però existeixen algunes solucions.", + "li0": "Les dades subjectives (com ara ressenyes) no són adequades per a OpenStreetMap. Tanmateix, MapComplete té una integració amb Mangrove.reviews, un lloc web de revisió amb llicència oberta", + "li1": "Els esdeveniments no es registren, ni tampoc les obres viàries que només duren uns quants dies.", + "li2": "Les dades temporals (per exemple, estadístiques de qualitat de l'aire, intensitat del trànsit, ...) no es poden emmagatzemar a OpenStreetMap, ja que són difícils de verificar per un voluntari. Tingues en compte que, si aquestes dades estan disponibles en un altre lloc, encara es poden visualitzar a MapComplete com a capa addicional.", + "title": "Les dades no són acceptables per OpenStreetMap" + } }, "indexPage": { "button": "Descobreix els nostres serveis", "hook": "Necessites ajuda professional?", "hookMore": "Podem ajudar a configurar enquestes, importacions de dades i consultoria OpenStreetMap" }, + "intro": "El desenvolupador de MapComplete ofereix suport professional. Aquest document descriu algunes de les possibilitats, preguntes habituals i els límits de MapComplete", + "osmTitle": "Què poden fer OpenStreetMap i MapComplete per a la vostra organització?", "services": { - "title": "Serveis de Mapcomplete", + "intro": "El desenvolupador de MapComplete us pot ajudar amb els serveis següents:", "li0": "Configurar una petició adaptada a les vostres necessitats", - "li4": "Formació sobre com baixar dades filtrades d'OpenStreetMap", + "li1": "Ajuda a configurar el flux de dades intern per integrar OpenStreetMap", "li2": "Formació sobre com aportar dades amb MapComplete", "li3": "Formació avançada (per exemple, per a l'equip GIS) sobre com afegir dades avançades a OpenStreetMap", - "intro": "El desenvolupador de MapComplete us pot ajudar amb els serveis següents:", - "li1": "Ajuda a configurar el flux de dades intern per integrar OpenStreetMap" + "li4": "Formació sobre com baixar dades filtrades d'OpenStreetMap", + "outro": "Aquests serveis s'ofereixen a preus competitius. Es pot configurar una petició senzilla sense suport addicional per tan sols 2000 € i un petit cost addicional d'hostatjament anual.", + "title": "Serveis de Mapcomplete" }, - "title": "Suport professional amb MapComplete", + "text0": "

    Mantenir un conjunt de geodades actualitzades és difícil, propens a errors i costós.
    Per fer més gran la ferida, moltes organitzacions acaben recopilant les mateixes dades de manera independent, donant lloc a esforços duplicats i dades no estandarditzades. formats i molts conjunts de dades incomplets i sense manteniment.

    Al mateix temps, hi ha una comunitat enorme que reuneix moltes geodades en una base de dades compartida, global i estandaritzada, és a dir, OpenStreetMap.org.

    ", "text1": "

    MapComplete és l'editor per facilitar la contribució de dades a OpenStreetMap.

    ", - "intro": "El desenvolupador de MapComplete ofereix suport professional. Aquest document descriu algunes de les possibilitats, preguntes habituals i els límits de MapComplete", - "osmTitle": "Què poden fer OpenStreetMap i MapComplete per a la vostra organització?" + "title": "Suport professional amb MapComplete" }, "reviews": { "affiliated_reviewer_warning": "(Ressenya afiliada)", @@ -500,16 +534,20 @@ }, "translations": { "activateButton": "Ajudar a traduir MapComplete", + "completeness": "Les traduccions de {theme} en {language} tenen un {percentage}%: {translated} cadenes de {total} es tradueixen", "deactivate": "Deshabilitar els botons de traducció", - "missing": "{count} cadenes sense traduir", - "notImmediate": "Les traduccions no s'actualitzen directament. Això sol trigar uns quants dies", + "help": "Fes clic a la icona 'tradueix' al costat d'una cadena per introduir o actualitzar un fragment de text. Necessites un compte de Weblate per a això. Crea'n un amb el teu nom d'usuari OSM per desbloquejar automàticament el mode de traducció.", "isTranslator": "El mode de traducció està actiu, ja que el vostre nom d'usuari coincideix amb el nom d'un traductor anterior", - "completeness": "Les traduccions de {theme} en {language} tenen un {percentage}%: {translated} cadenes de {total} es tradueixen" + "missing": "{count} cadenes sense traduir", + "notImmediate": "Les traduccions no s'actualitzen directament. Això sol trigar uns quants dies" }, "validation": { "color": { "description": "Un color o codi hex" }, + "date": { + "description": "Una data, començant per l'any" + }, "decimal": { "description": "Un número" }, @@ -518,8 +556,8 @@ }, "email": { "description": "Adreça de correu electrònic", - "noAt": "Una adreça de correu electrònic ha de contenir una @", - "feedback": "Aquesta adreça de correu electrònic no és vàlida" + "feedback": "Aquesta adreça de correu electrònic no és vàlida", + "noAt": "Una adreça de correu electrònic ha de contenir una @" }, "float": { "description": "un número", @@ -529,10 +567,10 @@ "description": "un número sencer" }, "nat": { + "description": "un nombre positiu, sencer o zero", "mustBePositive": "Aquest número ha de ser positiu", "mustBeWhole": "Només s'accepten números sencers", - "notANumber": "Escriu un número", - "description": "un nombre positiu, sencer o zero" + "notANumber": "Escriu un número" }, "opening_hours": { "description": "Horari d'obertura" @@ -554,16 +592,13 @@ "text": { "description": "un tros de text" }, + "tooLong": "El text és massa llarg, es permeten com a màxim 255 caràcters. Ara tens {count} caràcters", "url": { "description": "enllaç a un lloc web", "feedback": "Aquesta adreça web no és vàlida" }, "wikidata": { "description": "Un identificador de Wikidata" - }, - "date": { - "description": "Una data, començant per l'any" - }, - "tooLong": "El text és massa llarg, es permeten com a màxim 255 caràcters. Ara tens {count} caràcters" + } } } diff --git a/langs/da.json b/langs/da.json new file mode 100644 index 000000000..ddcedb245 --- /dev/null +++ b/langs/da.json @@ -0,0 +1,593 @@ +{ + "centerMessage": { + "loadingData": "Indlæser data…", + "ready": "Færdig!", + "retrying": "Indlæsning af data fejlede. Prøver igen om {count} sekunder…", + "zoomIn": "Zoom ind for at se og redigere data" + }, + "delete": { + "cancel": "Afbryd", + "cannotBeDeleted": "Dette element kan ikke slettes", + "delete": "Slet", + "explanations": { + "hardDelete": "Dette punkt vil blive slettet på OpenStreetMap. Det kan gendannes af en øvet bidragsyder", + "selectReason": "Angiv venligst hvorfor dette element burde slettes", + "softDelete": "Dette element vil blive opdateret og skjult for dette program {reason}" + }, + "isDeleted": "Dette element er slettet", + "isntAPoint": "Kun punkter skal slettes, det valgte element er en vej, et areal eller en relation.", + "loading": "Undersøger egenskaber for at finde ud af om dette element kan slettes.", + "loginToDelete": "Du skal være logget ind for slette et punkt", + "notEnoughExperience": "Punktet blev lavet af en anden.", + "onlyEditedByLoggedInUser": "Dette punkt er kun blevet redigeret af dig selv, du kan roligt slette det.", + "partOfOthers": "Dette punkt er en del af en vej eller relation og kan ikke direkte slettes.", + "readMessages": "Du har ulæste beskeder. Læs dem for du slette et punkt - nogen kan have tilbagemeldinger", + "reasons": { + "disused": "Dette element er nedlagt eller fjernet", + "duplicate": "Dette punkt er en dublet af et andet element", + "notFound": "Dette element kunne ikke findes", + "test": "Dette var et prøvepunkt - elementet var der aldrig rigtigt" + }, + "safeDelete": "Dette punkt kan slettes uden risiko.", + "useSomethingElse": "Brug i stedet en anden OpenStreetMap editor til at slette det", + "whyDelete": "Hvorfor skal dette punkt slettes?" + }, + "favourite": { + "loginNeeded": "

    Log ind

    En personlig opsætning er kun til rådighed for OpenStreetMap-brugere", + "panelIntro": "

    Dit personlige tema

    Aktiver dit favoritlag fra et af alle de officelle temaer", + "reload": "Genindlæs data" + }, + "general": { + "about": "Ret og tilføj nemt til Openstreetmap for et bestemt tema", + "aboutMapcomplete": "

    Om MapComplete

    Brug det til at tilføje OpenStreetMap information om et bestemt tema. Besvar spørgsmål, og i løbet af få minutter er dine bidrag tilgængelige overalt. temabestyreren definerer elementer, spørgsmål og sprog for temaet.

    Find ud af mere

    MapComplete tilbyder altid det næste trin for at lære mere om OpenStreetMap.

    • Når det er indlejret på et websted, linker iframe-en til et fuldskærms MapComplete
    • Fuldskærmsversionen tilbyder information om OpenStreetMap
    • Man kan se det uden at logge ind, men redigering kræver en OSM-konto.
    • Hvis du ikke har logget ind, vil du blive bedt om at gøre det
    • Når du har besvaret et enkelt spørgsmål, kan du tilføje nye punkter til kortet
    • Efter et stykke tid bliver faktiske OSM-tags vist, senere igen links til wiki-en


    Bemærkede du et problem? Har du enanmodning om en ny funktion? Vil du hjælpe med at oversætte? Gå til kildekoden eller issue trackeren.

    Vil du se dit fremskridt? Følg antallet af rettelser på OsmCha.

    ", + "add": { + "addNew": "Tilføj {category}", + "addNewMapLabel": "Klik her for at tilføje et nyt punkt", + "confirmButton": "Tilføj en {category}
    Din tilføjelse er synlig for alle
    ", + "confirmIntro": "

    Tilføj en {title}?

    Punktet du opretter her vil være synligt for alle. Tilføj kun ting til kortet, hvis de virkelig findes. Mange programmer bruger disse data.", + "disableFilters": "Slå alle filtre fra", + "disableFiltersExplanation": "Nogle elementer kan være skjult af et filter", + "hasBeenImported": "Punktet er allerede importeret", + "import": { + "hasBeenImported": "Objektet blev importeret", + "howToTest": "For at afprøve, tilføj test=true eller backend=osm-test til URL-en. Ændringssættet vil blive udskrevet på konsollen. Opret venligst en PR for at publicere dette tema og dermed aktivere importknappen.", + "importTags": "Dette element vil modtage {tags}", + "officialThemesOnly": "Importknappen er slået fra for uofficielle temaer for at undgå uheld", + "wrongType": "Dette element er ikke et punkt eller en vej og kan ikke importeres", + "zoomInMore": "Zoom mere ind for at importere dette element" + }, + "importTags": "Dette element modtager {tags}", + "intro": "Du klikkede et sted, hvor der endnu ikke er kendt data.
    ", + "layerNotEnabled": "Laget {layer} er ikke slået til. Slå laget til for at tilføje et punkt", + "openLayerControl": "Åben kontrolboksen for lag", + "pleaseLogin": "Log venligst ind for at tilføje et nyt punkt", + "presetInfo": "Det nye POI vil have {tags}", + "stillLoading": "Data indlæses stadig. Vent venligt lidt for du tilføjet et nyt punkt.", + "title": "Tilføj et nyt punkt?", + "warnVisibleForEveryone": "Til tilføjelse vil være synlig for alle", + "wrongType": "Dette element er ikke et punkt eller en vej og kan ikke importeres", + "zoomInFurther": "Zoom mere ind fore at tilføje et punkt.", + "zoomInMore": "Zoom mere ind for at importere dette element" + }, + "apply_button": { + "appliedOnAnotherObject": "Objektet {id} modtager {tags}", + "isApplied": "Ændringerne er anvendt" + }, + "attribution": { + "attributionContent": "

    Alle data leveres af OpenStreetMap, frit genanvendelige under Open DataBase Licensen.

    ", + "attributionTitle": "Meddelelse om tilskrivning", + "codeContributionsBy": "MapComplete er lavet af {contributors} og {hiddenCount} flere bidragsydere", + "donate": "Støt MapComplete økonomisk", + "editId": "Åben OpenStreetMap onlineeditoren her", + "editJosm": "Rediger her med JOSM", + "iconAttribution": { + "title": "Brugte ikoner" + }, + "josmNotOpened": "Kunne ikke komme i kontakt med JOSM. Sørg for at den er åbnet og at fjernbetjening er slået til", + "josmOpened": "JOSM er åbnet", + "mapContributionsBy": "Aktult synligt data har rettelser lavet af {contributors}", + "mapContributionsByAndHidden": "De aktuelt synlige rettelser er lavet af {contributors} og {hiddenCount} flere bidragsydere", + "openIssueTracker": "Rapporter en fejl", + "openMapillary": "Åbn Mapillary her", + "openOsmcha": "De de seneste rettelser lavet med {theme}", + "themeBy": "Tema vedligeholdt af {author}", + "translatedBy": "MapComplete er oversat af {contributors} og {hiddenCount} flere bidragsydere" + }, + "back": "Tilbage", + "backToMapcomplete": "Tilbage til temaoversigten", + "backgroundMap": "Baggrundskort", + "cancel": "Afbryd", + "confirm": "Bekræft", + "customThemeIntro": "

    Brugergeneredede temaer

    Disse er tidligere sete bruger-genererede temaer.", + "download": { + "downloadAsPdf": "Hent en PDF med det aktuelle kort", + "downloadAsPdfHelper": "Ideelt til at udskrive det aktuelle kort", + "downloadAsSvg": "Hent en SVG med det aktuelle kort", + "downloadCSV": "Hent synligt data som CSV", + "downloadCSVHelper": "Kompatibel med LibreOffice Calc, Excel, …", + "downloadFeatureAsGeojson": "Hent som GeoJson fil", + "downloadFeatureAsGpx": "Hent som GPX fil", + "downloadGeoJsonHelper": "Kompatibel med QGIS, ArcGIS, ESRI, …", + "downloadGeojson": "Hent synlig data som GeoJSON", + "downloadGpx": "Hent som GPX fil", + "downloadGpxHelper": "En GPX-fil kan bruges med de fleste navigationsenheder og programmer", + "exporting": "Eksporterer…", + "includeMetaData": "Inkluder metadata (sidste editor, beregnede værdier, ...)", + "licenseInfo": "

    Ophavsretsmeddelelse

    De leverede data er tilgængelige under ODbL. Genbrug til alle formål er gratis, men
    • tilskrivningen © OpenStreetMap contributors kræves
    • Enhver ændring skal bruge licensen
    Læs venligst hele ophavsretsmeddelelsen for detaljer.", + "noDataLoaded": "Der er endnu ikke indlæst noget data. Nedhentning vil snart være tilgængelig", + "title": "Hent synligt data", + "uploadGpx": "Upload dit spor til OpenStreetMap" + }, + "error": "Noget gik galt", + "example": "Eksempel", + "examples": "Eksempler", + "fewChangesBefore": "Besvar venligst nogle få spørgsmål om eksisterende punkter før du tilføjer et nyt punkt.", + "getStartedLogin": "Log in med OpenStreetMap for at komme i gang", + "getStartedNewAccount": " eller lav en ny konto", + "goToInbox": "Åbn indboks", + "histogram": { + "error_loading": "Kunne ikke indlæse histogrammet" + }, + "layerSelection": { + "title": "Vælg lag", + "zoomInToSeeThisLayer": "Zoom ind for at se dette lag" + }, + "loading": "Indlæser...", + "loadingTheme": "Indlæser {theme}...", + "loginFailed": "Det mislykkedes at logge ind på OpenStreetMap", + "loginOnlyNeededToEdit": "hvis du vil redigere kortet", + "loginToStart": "Log ind for at besvare dette spørgsmål", + "loginWithOpenStreetMap": "Logind med OpenStreetMap", + "logout": "Log ud", + "morescreen": { + "createYourOwnTheme": "Lave dit eget MapComplete tema fra bunden af", + "hiddenExplanation": "Disse temaer er kun tilgængelige med linket. Du har opdaget {hidden_discovered} af {total_hidden} skjulte temaer.", + "intro": "

    Flere tematiske kort?

    Nød du at indsamle geodata?
    Der er flere temaer til rådighed.", + "previouslyHiddenTitle": "Tidligere besøgte skjulte temaer", + "requestATheme": "Hvis de efterspørger et specialfremstillet tema, så bed om det i issue tracker-en", + "streetcomplete": "En anden lignende applikation er StreetComplete." + }, + "nameInlineQuestion": "{category} hedder $$$", + "next": "Næste", + "noNameCategory": "{category} uden navn", + "noTagsSelected": "Ingen tags valgt", + "notValid": "Vælg en gyldig værdi for at gå videre", + "number": "tal", + "oneSkippedQuestion": "Et spørgsmål er ignoreret", + "openStreetMapIntro": "

    At Åbent kort

    Et som alle kan bruge og redigere frit. Eet sted at gemme al geo-information. Forskellige, små, inkompatible og forældede kort er der ikke brug for nogen steder.

    OpenStreetMap er ikke fjendens kort. Kortet kan bruges frit (med kreditering og publicering af ændringer af data). Alle kan tilføje mere data og rette fejl. Denne website bruger OpenStreetMap. Al data kommer derfra, og dine svar og rettelser vil blive bruge alle vegne.

    Mange folk og apps bruger allerede OpenStreetMap: Organic Maps, OsmAnd, men også kortene på Facebook, Instagram, Apple-maps and Bing-maps er (delvist) drevet af OpenStreetMap.

    ", + "openTheMap": "Åbn kortet", + "opening_hours": { + "closed_permanently": "Lukket med en ukendt varighed", + "closed_until": "Lukket indtil {date}", + "error_loading": "Fejl: Kunne ikke visualisere disse åbningstider.", + "loadingCountry": "Bestemmer land…", + "not_all_rules_parsed": "Disse åbningstider er komplicerede. De følgende regler er ignoreret i inputelementet:", + "openTill": "indtil", + "open_24_7": "døgnåbent", + "open_during_ph": "På offentlige helligdage, er dette", + "opensAt": "fra", + "ph_closed": "lukket", + "ph_not_known": " ", + "ph_open": "åbent", + "ph_open_as_usual": "åbent som sædvanligt" + }, + "osmLinkTooltip": "Læs dette objekt i en browser på OpenStreetMap for historik og flere rettemuligheder", + "pdf": { + "attr": "Kortdata © OpenStreetMap Contributors, bearbejdelser under ODbL", + "attrBackground": "Baggrundslag: {background}", + "generatedWith": "Genereret med MapComplete.osm.be", + "versionInfo": "v{version} - genereret den {date}" + }, + "pickLanguage": "Vælg et sprog: ", + "poweredByOsm": "Drevet af OpenStreetMap", + "questions": { + "emailIs": "Emailadressen på denne {category} er {email}", + "emailOf": "Hvad er emailadressen på {category}?", + "phoneNumberIs": "Telefonnummeret på denne/dette {category} er {phone}", + "phoneNumberOf": "Hvad er telefonnummeret for {category}?", + "websiteIs": "Hjemmeside: {website}", + "websiteOf": "Hvad er hjemmesiden for {category}?" + }, + "readYourMessages": "Læs venligst alle dine OpenStreetMap beskeder før du tilføjer et nyt punkt.", + "removeLocationHistory": "Slet placeringshistorikken", + "returnToTheMap": "Vend tilbage til kortet", + "save": "Gem", + "screenToSmall": "Åbn {theme} i et nyt vindue", + "search": { + "error": "Noget gik galt…", + "nothing": "Intet fundet…", + "search": "Vælg en sted", + "searching": "Søger…" + }, + "sharescreen": { + "addToHomeScreen": "

    Tilføj til din hjemmeskærm

    Du kan let tilføje denne hjemmeside til din smartphones hjemmeskærm for at få den integreret. Klik på 'Tilføj til hjemmeskærm' knappen i URL-feltet for at gøre det.", + "copiedToClipboard": "Link kopierer til udklipsholder", + "editThemeDescription": "Tilføj eller ret spørgsmål til dette korttema", + "editThisTheme": "Ret dette tema", + "embedIntro": "

    Indlejr på din hjemmeside

    Indlejr venligst dette kort på din hjemmeside.
    Vi tilskynder dig til det - du behøver ikke engang at spørge om tilladelse.
    Det det frit og gratis og vil altid være det. Jo flere der bruger det, jo mere værdifuldt bliver det.", + "fsAddNew": "Slå 'tilføj nyt POI' knappen til", + "fsGeolocation": "Slå 'geolocate-me' knappen til (kun mobil)", + "fsIncludeCurrentBackgroundMap": "Inkluder det aktuelle baggrundsvalg {name}", + "fsIncludeCurrentLayers": "Inkluder det aktuelle valg af lag", + "fsIncludeCurrentLocation": "Inkludere det aktuelle sted", + "fsLayerControlToggle": "Start med lagkontrollen udvidet", + "fsLayers": "Slå lagkontrollen til", + "fsSearch": "Slå søgefeltet til", + "fsUserbadge": "Slå loginknappen til", + "fsWelcomeMessage": "Vis velkomstbeskeden og tilknyttede faner", + "intro": "

    Del dette kort

    Del dette kort ved at kopiere linket nedenunder og send det til venner og familie:", + "thanksForSharing": "Tak for at dele!" + }, + "skip": "Spring over dette spørgsmål", + "skippedQuestions": "Nogle spørgsmål er sprunget over", + "testing": "Testing - ingen ændringer vil blive gemt", + "weekdays": { + "abbreviations": { + "friday": "Fre", + "monday": "Man", + "saturday": "Lør", + "sunday": "Søn", + "thursday": "Tor", + "tuesday": "Tir", + "wednesday": "Ons" + }, + "friday": "Fredag", + "monday": "Mandag", + "saturday": "Lørdag", + "sunday": "Søndag", + "thursday": "Torsdag", + "tuesday": "Tirsdag", + "wednesday": "Onsdag" + }, + "welcomeBack": "Du er logget ind, velkommen tilbage!", + "wikipedia": { + "createNewWikidata": "Opret et nyt Wikidata element", + "doSearch": "Søg ovenfor for at se resultater", + "failed": "Indlæsning af Wikipedia-artikel mislykkedes", + "loading": "Indlæser Wikipedia...", + "noResults": "Intet fundet for {search}", + "noWikipediaPage": "Dette Wikidata-element har endnu ingen tilknyttet Wikipedia artikel.", + "previewbox": { + "born": "Født: {value}", + "died": "Død: {value}" + }, + "searchWikidata": "Søg på Wikidata", + "wikipediaboxTitle": "Wikipedia" + } + }, + "image": { + "addPicture": "Tilføj Billede", + "ccb": "under CC-BY-licensen", + "ccbExplanation": "The CC-BY licensen siger, at alle kan bruge dit billede til ethvert formål, men at de skal kreditere dig", + "ccbs": "under CC-BY-SA-licensen", + "ccbsExplanation": "CC-BY-SA licensen siger, at alle kan bruge dit billede til ethvert formål, men at de skal kreditere dig og at bearbejdelser af billedet skal offentliggøres under samme licens", + "cco": "i offentligt domæne", + "ccoExplanation": "At tilføje et billede til det offentlig domæne betyder, at alle kan gøre hvad som helst med dit billede", + "doDelete": "Fjern billede", + "dontDelete": "Afbryd", + "isDeleted": "Slettet", + "pleaseLogin": "Log venligst ind for at tilføje et billede", + "respectPrivacy": "Tag ikke billeder af mennesker eller nummerplader. Upload ikke Google Maps, Google Streetview, eller fra andre ophavsresbeskyttede kilder.", + "toBig": "Dit billede er for stort da det er {actual_size}. Brug venligst billeder, der er højst {max_size}", + "uploadDone": "Dit billede er tilføjet. Tak for hjælpen!", + "uploadFailed": "Kunne ikke uploade dit billede. Er du forbundet til Internettet og tillader du tredieparts API'er. Brave browseren eller uMatrix plugin'et kunne blokerer dem.", + "uploadMultipleDone": "{count} billeder tilføjet. Tak for at hjælpe til!", + "uploadingMultiple": "Uploader {count} billeder…", + "uploadingPicture": "Uploading dit billede…", + "willBePublished": "Dit billede vil blive offentliggjort " + }, + "importHelper": { + "askMetadata": { + "downloadGeojson": "Hent geojson", + "giveDescription": "Skriv venligst en lille beskrivelse til nogen, som ser beskeden. A god besked beskriver hvad bidragsyderen skal gøre, fx; Der kunne være en bænk her. Hvis du er i nærheden, kunne du venligst checke og indikere om bænken findes eller ej? (Et link til MapComplete vil automatisk blive tilføjet)", + "giveSource": "Hvad er kilden til disse data. Hvis 'source' er sat på elementen, vil denne værdi blive ignoreret", + "giveWikilink": "På hvilken wikiside kan man finde mere information om denne import?", + "intro": "Angiv venligst noget mere information før du tilføjer {count} noter.", + "orDownload": "Alternativt kan du hente datasættet og importere det direkte", + "shouldBeOsmWikilink": "Forventede et link til en side på wiki.openstreetmap.org", + "shouldBeUrl": "Ikke en gyldig URL", + "shouldNotBeHomepage": "Nej, hjemmesiden er heller ikke tilladt. Indtast URL'en for en rigtig wikipage, der dokumenterer din import", + "title": "Sæt metadata" + }, + "compareToAlreadyExistingNotes": { + "completelyImported": "Alle de foreslåede punkter har (eller havde) allerede en importnote", + "loading": "Henter noter fra OSM", + "loadingFailed": "Det mislykkedes at indlæse noter fordi {error}", + "mapExplanation": "De røde elementer på det næste kort er alle datapunkter fra dit datasæt. Der er {length} elementer i dit dataset.", + "noPreviousNotesFound": "Ingen tidligere importnoter fundet", + "nothingNearby": "Ingen af de foreslåede punkter har en importnote i nærheden", + "someNearby": "{hasNearby} punkter har allerede en eksisterende importnote indenfor {distance} meter", + "title": "Sammenlig med eksisterende noter", + "titleLong": "Sammenlign med allerede eksisterende 'til-import'-noter", + "wontBeImported": "Disse datapunkter vil ikke blive importeret og er vist som røde prikker på kortet nedenunder" + }, + "confirmProcess": { + "contactedCommunity": "Jeg kontaktede (det lokale) fællesskab(et) angående denne import", + "licenseIsCompatible": "Licensen for data, der skal importeres, tillader at det importeres til OSM. OSM har lov til at videredistribuere det kommercielt, med kun minimal kreditering", + "readImportGuidelines": "Jeg har læst importeringsvejledningerne på OSM wiki'en", + "title": "Licens og fællesskab", + "titleLong": "Har du gennemgået importprocessen?", + "wikipageIsMade": "Processen er dokumenteret på OSM-wikien (du får senere brug for dette link)" + }, + "conflationChecker": { + "cacheExpired": "Cachen udløb", + "downloadOverpassData": "Hent den indlæste geojson fra overpass", + "importCandidatesCount": "De {count} røde elementer på det følgende kort er alle dine importkandidater.", + "loadedDataAge": "Det indlæste data er fra cachen og er {age} gammelt", + "mapShowingNearbyIntro": "Det følgende kort viser elementer til import, som indeholder et OSM-element ", + "nearbyWarn": "De {count} røde elementer på det følgende kort vil ikke blive importeret!", + "nothingLoaded": "Ingen elementer er indlæst fra OpenStreetMap som matcher det aktuelle lag {name}", + "osmLoaded": "{count} elementer indlæst fra OpenStreetMap matcher laget {name}.", + "setRangeToZero": "Sæt rækkevidden til 0 eller 1 hvis du vil importere dem alle", + "states": { + "error": "Kunne ikke indlæse seneste data fra overpass pga {error}", + "idle": "Undersøger lokalt lager...", + "running": "Forespørger overpass...", + "unexpected": "Uventet tilstand {state}" + }, + "title": "Sammenlign med eksisterende data", + "titleLive": "Live data på OSM", + "titleNearby": "Elementer i nærheden", + "zoomIn": "Live data bliver vist på zoomniveau mindst {needed}. Det aktuelle zoomniveau er {current}" + }, + "createNotes": { + "creating": "Oprettede {count} noter ud af {total}", + "done": "Alle {count} noter er oprettet!", + "loading": "Vent mens vi indlæser...", + "openImportViewer": "Inspicerer fremgangen af dine noter i 'import_viewer'", + "title": "Noteoprettelse" + }, + "gotoImportViewer": "Inspicer dine tidligere importeringer", + "introduction": { + "description": "Importeringshjælperen konverterer et eksterns datasæt til noter. Det eksterne datasæt skal matche et af de eksisterende MapComplete lag. For hvert ting, du putter i importeringshjælperen, vil en enkelt note blive oprettet. Disse noter vises sammen med de relevante elementer i disse kort, så de nemt kan tilføjes.", + "importFormat": "En tekst i en note skulle have det følgende format for blive taget med", + "title": "Introduktion" + }, + "login": { + "lockNotice": "Denne side er låst. Du skal have {importHelperUnlock}ændringssæt før du får adgang her.", + "loggedInWith": "De er nu logget ind som {name} og har lavet {csCount} ændringssæt", + "loginIsCorrect": "{name} er den rigtige konto til at lave importnoter med.", + "loginRequired": "Du skal være logget ind for at gå videre", + "title": "Log ind", + "userAccountTitle": "Vælg en brugerkonto" + }, + "mapPreview": { + "confirm": "Elementerne er det rigtige sted på kortet", + "mismatch": "{count} elementer matchede ikke det valgte lag. Sørg for at mærkerne, der indikerer typen er der, nemlig {tags}", + "selectLayer": "Hvilket lag passer denne importering med?", + "title": "Forhåndsvisning af kort" + }, + "noteParts": { + "datasource": "Originalt data fra {source}", + "importEasily": "Tilføj nemt dette punkt med MapComplete:", + "wikilink": "Mere information om denne importering kan findes på {wikilink}" + }, + "previewAttributes": { + "allAttributesSame": "Alle elementer til importering har dette mærke", + "inspectDataTitle": "Inspicer data for {count} elementer til importering", + "inspectLooksCorrect": "Disse værdier ser korrekte ud", + "someHaveSame": "{count} elementer til importering har dette mærke, det er {percentage}% af totalen", + "title": "Inspicer attributter" + }, + "selectFile": { + "description": "Vælg en .csv eller .geojson fil for at komme i gang", + "errDuplicate": "Flere kolonner har det samme navn", + "errNoLatOrLon": "Headeren indeholder ikke `lat` eller `lon`", + "errNoName": "Nogle kolonner har ikke et navn", + "errNotFeatureCollection": "Den indlæste JSON fil er ikke en geojson-featurecollection", + "errPointsOnly": "Den indlæste JSON-fil skal kun indeholde punkter", + "fileFormatDescription": "Vælg en .csv eller en .geojson fil", + "noFilesLoaded": "Ingen fil er indlæst", + "title": "Vælg fil" + }, + "selectTheme": { + "displayNonMatchingCount": "{length} objekter passer ikke med nogen forudindstillinger", + "missing": "Forventede $k}={v}, men det mangler helt", + "needsTags": "{title} skal have mærker {tags}", + "notApplicable": "Forudindstillet {title} kan ikke anvendes:", + "title": "Vælg et tema" + }, + "testMode": "Testmodus - vil ikke faktisk importere noter", + "title": "Importeringshjælper" + }, + "importInspector": { + "title": "Undersøg og håndter noter" + }, + "importLayer": { + "alreadyMapped": "Der er allerede en anden {title} på kortet - dette punkt er en dublet", + "description": "Et lag som importerer poster for {title}", + "layerName": "Mulig {title}", + "notFound": "Jeg kunne ikke finde {title} - fjern det", + "popupTitle": "Mulig {title}" + }, + "index": { + "featuredThemeTitle": "Fremhævet denne uge", + "pickTheme": "Vælg et tema nedenfor for at komme i gang.", + "title": "Velkommen til MapComplete" + }, + "move": { + "cancel": "Afbryd flytning", + "cannotBeMoved": "Dette element kan ikke flyttes.", + "confirmMove": "Flyt her", + "inviteToMove": { + "generic": "Flyt dette punkt", + "reasonInaccurate": "Forbedr nøjagtigheden for dette punkt" + }, + "inviteToMoveAgain": "Flyt dette punkt igen", + "loginToMove": "Du skal være logget ind for at flytte et punkt", + "moveTitle": "Flyt dette punkt", + "pointIsMoved": "Dette punkt er blevet flyttet", + "selectReason": "Hvorfor flytter du dette objekt?", + "whyMove": "Hvorfor vil du flytte dette punkt?", + "zoomInFurther": "Zoom mere ind for bekræfte denne flytning" + }, + "notes": { + "addAComment": "Tilføj en kommentar", + "addComment": "Tilføj kommentar", + "addCommentAndClose": "Tilføj kommentar og luk", + "addCommentPlaceholder": "Tilføj en kommentar...", + "anonymous": "Anonym bruger", + "closeNote": "Luk note", + "createNote": "Lav en ny note", + "createNoteTitle": "Opret en ny note her", + "disableAllNoteFilters": "Slå alle filtre fra", + "isClosed": "Denne note er løst", + "isCreated": "Din note er oprettet!", + "loginToAddComment": "Log ind for at tilføje en kommentar", + "loginToAddPicture": "Log ind for tilføje et billede", + "loginToClose": "Log ind for at lukke denne note", + "noteIsPublic": "Dette vil kunne ses af alle", + "noteLayerDoEnable": "Slå laget, der viser noter, til", + "noteLayerHasFilters": "Nogle noter kan være skjult af et filter", + "reopenNote": "Genåbn note", + "reopenNoteAndComment": "Genåbn note og kommenter", + "textNeeded": "Indtast en beskrivende tekst for at oprette en note", + "typeText": "Indtast noget tekst for at tilføje en kommentar" + }, + "privacy": { + "geodataTitle": "Din placering", + "miscCookiesTitle": "Andre cookies", + "title": "Privatlivspolitik", + "trackingTitle": "Statistisk data", + "whileYoureHere": "Sætter du pris på privatliv?" + }, + "professional": { + "aboutMc": { + "internalUse": { + "title": "Brug af data i interne processer" + }, + "layers": { + "title": "Hvilke data kan blive vist med MapComplete?" + }, + "survey": { + "title": "Kortlægningsmuligheder" + }, + "title": "Brug MapComplete i din organisation" + }, + "aboutOsm": { + "aboutOsm": { + "li3": "og meget, meget mere…", + "title": "Hvad er OpenStreetMap?" + }, + "benefits": { + "title": "Fordele ved OSM økosystemet" + }, + "license": { + "li0": "Et produkt, der bruger OpenStreetMap data, skal kreditere.", + "outro": "Licensen har nogle få konsekvenser - Disse er forklaret nedenfor.", + "title": "Licensen" + }, + "vandalism": { + "intro": "Eftersom alle kan redigere data, er det faktisk muligt, at der forekommer en ondsindet ændring. Det er imidlertid ekstremt sjælden af nogle få årsager:", + "li0": "den tekniske barriere for at foretage ændringer er høj", + "li4": "I Belgien (og visse andre lande), bliver den første ændring af ny bidragsyder systematisk checket og hvis nødvendigt, rettet.", + "title": "Hvad med vandalisme?" + } + }, + "drawbacks": { + "licenseNuances": { + "li0": "Al data kan bruges til ethvert formål - deriblandt kommercielle formål", + "title": "Konsekvenser af ODbL: nogle use cases", + "usecaseGatheringOpenData": { + "title": "Indsamle åben data" + }, + "usecaseMapDifferentSources": { + "li1": "...hvorimod alle-rettigheder-forbeholdes licenserne ville forbyde dette.", + "title": "Dannelse af kort fra forskellige kilder" + } + }, + "title": "Nogle få ulemper at holde sig for øje", + "unsuitedData": { + "title": "Data uegnet for OpenStreetMap" + } + }, + "indexPage": { + "button": "Opdag vore tjenester", + "hook": "Brug for professionel støtte?" + }, + "services": { + "intro": "Udviklerne af MapComplete kan hjælpe dig med følgende tjenester:", + "li0": "Opsætning af et tema skræddersyet efter dine behov", + "li1": "Hjælp med opsætning af internt data flow til integration med OpenStreetMap", + "title": "MapComplete tjenester" + }, + "title": "Professionel støtte med MapComplete" + }, + "reviews": { + "affiliated_reviewer_warning": "(Tilknyttet anmeldelse)", + "no_rating": "Ingen vurdering givet", + "plz_login": "Log ind for at give en anmeldelse", + "posting_as": "Anmelder som", + "saved": "Anmeldelse gemt. Tak for at bidrage!", + "saving_review": "Gemmer…", + "title": "{count} Anmeldelser", + "title_singular": "En anmeldelse", + "write_a_comment": "Skriv en anmeldelse…" + }, + "split": { + "cancel": "Afbryd", + "hasBeenSplit": "Denne vej er blevet opdelt", + "split": "Opdel" + }, + "translations": { + "activateButton": "Hjælp med at oversætte MapComplete", + "deactivate": "Slå oversættelsesknapper fra", + "missing": "{count} uoversatte strenge" + }, + "validation": { + "color": { + "description": "En farve eller hex-kode" + }, + "date": { + "description": "En dato, der starter med årstallet" + }, + "decimal": { + "description": "Et tal" + }, + "email": { + "description": "email-adresse", + "feedback": "Dette er ikke en gyldig emailadresse", + "noAt": "En emailadresse skulle indeholde et @" + }, + "float": { + "description": "et tal", + "feedback": "Dette er ikke et tal" + }, + "int": { + "description": "et heltal" + }, + "nat": { + "description": "et positivt heltal eller nul", + "mustBePositive": "Dette tal skal være positivt", + "mustBeWhole": "Kun heltal er tilladt", + "notANumber": "Indtast et tal" + }, + "opening_hours": { + "description": "Åbningstider" + }, + "pfloat": { + "description": "et positivt heltal" + }, + "phone": { + "description": "et telefonnummer", + "feedback": "Dette er ikke et gyldigt telefonnummer" + }, + "pnat": { + "description": "et positivt heltal", + "noZero": "Nul er ikke tilladt" + }, + "string": { + "description": "et stykke tekst" + }, + "text": { + "description": "et stykke tekst" + }, + "url": { + "description": "link til en webside", + "feedback": "Dette er ikke et gyldigt link" + }, + "wikidata": { + "description": "En Wikidata identifier" + } + } +} diff --git a/langs/de.json b/langs/de.json index 5226406d9..92f29e3c4 100644 --- a/langs/de.json +++ b/langs/de.json @@ -19,7 +19,7 @@ "loading": "Untersuchung der Eigenschaften, um zu prüfen, ob dieses Element gelöscht werden kann.", "loginToDelete": "Sie müssen angemeldet sein, um einen Punkt zu löschen", "notEnoughExperience": "Dieser Punkt wurde von jemand anderem erstellt.", - "onlyEditedByLoggedInUser": "Dieser Punkt wurde nur von Ihnen selbst bearbeitet, Sie können ihn sicher löschen.", + "onlyEditedByLoggedInUser": "Dieser Punkt wurde nur von Ihnen selbst bearbeitet, Sie können ihn gefahrlos löschen.", "partOfOthers": "Dieser Punkt ist Teil eines Weges oder einer Relation und kann nicht direkt gelöscht werden.", "readMessages": "Du hast ungelesene Nachrichten. Bitte beachte diese, bevor Du einen Punkt löschst - vielleicht hat jemand eine Rückmeldung", "reasons": { @@ -39,7 +39,7 @@ }, "general": { "about": "OpenStreetMap für ein bestimmtes Thema einfach bearbeiten und hinzufügen", - "aboutMapcomplete": "

    Über MapComplete

    Nutzen Sie es, um OpenStreetMap-Informationen zu einem einzigen Thema hinzuzufügen. Beantworten Sie Fragen, und innerhalb weniger Minuten sind Ihre Beiträge überall verfügbar. Der Theme-Maintainer definiert Elemente, Fragen und Sprachen dafür.

    Mehr erfahren

    MapComplete bietet immer den nächsten Schritt, um mehr über OpenStreetMap zu erfahren.

    • Wenn es in eine Website eingebettet wird, verlinkt der iframe zu einer Vollbildversion von MapComplete
    • Die Vollbildversion bietet Infos über OpenStreetMap
    • Das Betrachten funktioniert ohne Anmeldung, aber das Bearbeiten erfordert ein OSM-Konto.
    • Wenn Sie nicht angemeldet sind, werden Sie dazu aufgefordert
    • Sobald Sie eine Frage beantwortet haben, können Sie der Karte neue Punkte hinzufügen
    • Nach einer Weile werden aktuelle OSM-Tags angezeigt, die später mit dem Wiki verlinkt werden


    Haben Sie ein Problem bemerkt? Haben Sie einen Funktionswunsch? Möchten Sie bei der Übersetzung helfen? Besuchen Sie den Quellcode oder den Issue Tracker

    Möchten Sie Ihren Fortschritt sehen? Verfolgen Sie die Anzahl der Änderungen auf OsmCha.

    ", + "aboutMapcomplete": "

    Über MapComplete

    Nutzen Sie MapComplete, um OpenStreetMap-Informationen zu einem bestimmten Thema hinzuzufügen. Beantworten Sie Fragen, und in wenigen Minuten sind Ihre Beiträge überall verfügbar. Der Theme-Maintainer definiert Elemente, Fragen und Sprachen dafür.

    Mehr erfahren

    MapComplete bietet immer den nächsten Schritt, um mehr über OpenStreetMap zu erfahren.

    • In einer Website eingebettet, verlinkt der iframe zu einer Vollbildversion von MapComplete
    • Die Vollbildversion bietet Informationen über OpenStreetMap
    • Das Betrachten funktioniert ohne Anmeldung, aber das Bearbeiten erfordert ein OSM-Konto.
    • Wenn Sie nicht angemeldet sind, werden Sie dazu aufgefordert
    • Sobald Sie eine Frage beantwortet haben, können Sie der Karte neue Punkte hinzufügen
    • Nach einer Weile werden aktuelle OSM-Tags angezeigt, die später mit dem Wiki verlinkt werden


    Haben Sie ein Problem bemerkt? Haben Sie einen Funktionswunsch? Möchten Sie bei der Übersetzung helfen? Hier geht es zum Quellcode und Issue Tracker

    Möchten Sie Ihren Fortschritt sehen? Verfolgen Sie Ihre Änderungen auf OsmCha.

    ", "add": { "addNew": "Füge {category} hinzu", "addNewMapLabel": "Hier klicken, um ein neues Element hinzuzufügen", @@ -49,12 +49,12 @@ "disableFiltersExplanation": "Einige Elemente können durch einen Filter ausgeblendet sein", "hasBeenImported": "Dieser Punkt wurde bereits importiert", "import": { - "hasBeenImported": "Das Objekt wurde importiert.", - "officialThemesOnly": "Der Importbutton ist für nicht offizielle Themen deaktiviert um Störfälle zu vermeiden.", - "wrongType": "Dieses Element ist kein Punkt oder Weg und kann deshalb nicht importiert werden.", - "zoomInMore": "Vergrößere um das Feature zu importieren.", + "hasBeenImported": "Das Objekt wurde importiert", + "howToTest": "Um es zu testen, hänge test=true oder backend=osm-test an die URL an. Die Änderungen werden in der Konsole ausgegeben. Bitte erstelle einen PR um das Thema zu veröffentlichen das den Import Button freischält.", "importTags": "Das Element wird {tags} bekommen", - "howToTest": "Um es zu testen, hänge test=true oder backend=osm-test an die URL an. Die Änderungen werden in der Konsole ausgegeben. Bitte erstelle einen PR um das Thema zu veröffentlichen das den Import Button freischält." + "officialThemesOnly": "Die Import-Schaltfläche ist für inoffizielle Themen deaktiviert, um Störfälle zu vermeiden", + "wrongType": "Dieses Element ist kein Punkt oder Weg und kann deshalb nicht importiert werden", + "zoomInMore": "Ansicht vergrößern, um das Objekt zu importieren" }, "importTags": "Das Element erhält {tags}", "intro": "Sie haben auf eine Stelle in der Karte geklickt, an der noch keine Daten bekannt sind.
    ", @@ -70,28 +70,28 @@ "zoomInMore": "Vergrößern Sie die Ansicht, um dieses Element zu importieren" }, "apply_button": { - "isApplied": "Die Änderungen wurden gespeichert.", - "appliedOnAnotherObject": "Das Objekt {id} wird {tags} bekommen" + "appliedOnAnotherObject": "Das Objekt {id} wird {tags} bekommen", + "isApplied": "Die Änderungen werden übernommen" }, "attribution": { "attributionContent": "

    Alle Daten wurden bereitgestellt von OpenStreetMap, frei verwendbar unter der Open Database License.

    ", "attributionTitle": "Danksagung", - "codeContributionsBy": "MapComplete wurde von {contributors} und {hiddenCount} weiteren Beitragenden erstellt", - "donate": "Unterstütze MapComplete finanziell", - "editId": "Öffne den OpenStreetMap online Editor hier.", + "codeContributionsBy": "MapComplete wurde erstellt von {contributors} und {hiddenCount} weiteren Beitragenden", + "donate": "MapComplete finanziell unterstützen", + "editId": "Den OpenStreetMap Editor öffnen", "editJosm": "Bearbeite mit JOSM", "iconAttribution": { "title": "Verwendete Symbole" }, - "josmNotOpened": "JOSM konnte nicht erreicht werden. Stelle sicher, dass es geöffnet ist und Fernkontrolle aktiviert ist", + "josmNotOpened": "JOSM konnte nicht erreicht werden. Stelle sicher, dass es geöffnet ist und Fernkontrolle aktiviert ist", "josmOpened": "JOSM ist geöffnet", "mapContributionsBy": "Die aktuell sichtbaren Daten wurden editiert durch {contributors}", - "mapContributionsByAndHidden": "Die aktuell sichtbaren Daten wurden editiert durch {contributors} und {hiddenCount} weitere Beitragende", - "openIssueTracker": "Melde einen Fehler", - "openMapillary": "Öffne Mapillary hier", + "mapContributionsByAndHidden": "Die aktuell sichtbaren Daten wurden editiert von {contributors} und {hiddenCount} weiteren Beitragenden", + "openIssueTracker": "Einen Fehler melden", + "openMapillary": "Mapillary öffnen", "openOsmcha": "Letzte Bearbeitungen mit {theme} ansehen", "themeBy": "Thema betreut von {author}", - "translatedBy": "MapComplete wurde von {contributors}, {hiddenCount} und weiteren Mitwirkenden übersetzt." + "translatedBy": "MapComplete wurde übersetzt von {contributors}, {hiddenCount} und weiteren Mitwirkenden" }, "back": "Zurück", "backToMapcomplete": "Zurück zur Themenwahl", @@ -119,6 +119,7 @@ "title": "Sichtbare Daten herunterladen", "uploadGpx": "Lade deinen Track auf OpenStreetMap hoch" }, + "error": "Etwas ist schief gelaufen", "example": "Beispiel", "examples": "Beispiele", "fewChangesBefore": "Bitte beantworten Sie ein paar Fragen zu bestehenden Punkten, bevor Sie einen neuen Punkt hinzufügen.", @@ -134,6 +135,7 @@ }, "loading": "Laden...", "loadingTheme": "Lade {theme}...", + "loginFailed": "Einloggen zu OpenStreetMap fehlgeschlagen", "loginOnlyNeededToEdit": "zum Bearbeiten der Karte", "loginToStart": "Anmelden, um diese Frage zu beantworten", "loginWithOpenStreetMap": "Bei OpenStreetMap anmelden", @@ -147,12 +149,13 @@ "streetcomplete": "Eine ähnliche App ist StreetComplete." }, "nameInlineQuestion": "Der Name dieser {category} ist $$$", - "next": "Nächstes", + "next": "Weiter", "noNameCategory": "{category} ohne Namen", "noTagsSelected": "Keine Tags ausgewählt", + "notValid": "Gültigen Wert auswählen, um fortzufahren", "number": "Zahl", "oneSkippedQuestion": "Eine Frage wurde übersprungen", - "openStreetMapIntro": "

    Eine offene Karte

    Eine Karte, die jeder frei nutzen und bearbeiten kann. Ein einziger Ort, um alle Geoinformationen zu speichern. Unterschiedliche, kleine, inkompatible und veraltete Karten werden nirgendwo gebraucht.

    OpenStreetMap ist nicht die feindliche Karte. Die Kartendaten können frei verwendet werden (mit Benennung und Veröffentlichung von Änderungen an diesen Daten). Jeder kann neue Daten hinzufügen und Fehler korrigieren. Diese Webseite nutzt OpenStreetMap. Alle Daten stammen von dort, und Ihre Antworten und Korrekturen werden überall verwendet.

    Viele Menschen und Anwendungen nutzen bereits OpenStreetMap: Organic Maps, OsmAnd, aber auch die Karten bei Facebook, Instagram, Apple-maps und Bing-maps werden (teilweise) von OpenStreetMap bereichert.

    ", + "openStreetMapIntro": "

    Eine offene Karte

    Eine Karte, die jeder frei nutzen und bearbeiten kann. Ein einziger Ort, um alle Geoinformationen zu speichern. Unterschiedliche, kleine, inkompatible und veraltete Karten werden nirgendwo gebraucht.

    OpenStreetMap ist nicht die feindliche Karte. Die Kartendaten können frei verwendet werden (mit Benennung und Veröffentlichung von Änderungen an diesen Daten). Jeder kann neue Daten hinzufügen und Fehler korrigieren. Diese Webseite nutzt OpenStreetMap. Alle Daten stammen von dort, und Ihre Antworten und Korrekturen werden überall verwendet.

    Viele Menschen und Anwendungen nutzen bereits OpenStreetMap: Organic Maps, OsmAnd; auch die Kartendaten von Facebook, Instagram, Apple-maps und Bing-maps stammen (teilweise) von OpenStreetMap.

    ", "openTheMap": "Karte öffnen", "opening_hours": { "closed_permanently": "Geschlossen auf unbestimmte Zeit", @@ -177,6 +180,7 @@ "versionInfo": "v{version} - erstellt am {date}" }, "pickLanguage": "Sprache wählen: ", + "poweredByOsm": "Unterstützt von OpenStreetMap", "questions": { "emailIs": "Die E-Mail-Adresse dieser {category} lautet {email}", "emailOf": "Wie lautet die E-Mail-Adresse der {category}?", @@ -203,11 +207,11 @@ "editThisTheme": "Dieses Thema bearbeiten", "embedIntro": "

    Auf Ihrer Website einbetten

    Bitte betten Sie diese Karte in Ihre Webseite ein.
    Wir ermutigen Sie, es zu tun - Sie müssen nicht einmal um Erlaubnis fragen.
    Es ist kostenlos und wird es immer sein. Je mehr Leute sie benutzen, desto wertvoller wird sie.", "fsAddNew": "Schaltfläche 'neuen POI hinzufügen' aktivieren", - "fsGeolocation": "Die Schaltfläche 'Mich geolokalisieren' aktivieren (nur für Mobil)", - "fsIncludeCurrentBackgroundMap": "Den aktuellen Hintergrund übernehmen {name}", - "fsIncludeCurrentLayers": "Die aktuelle Ebenenauswahl übernehmen", + "fsGeolocation": "Schaltfläche 'Mich geolokalisieren' aktivieren (nur mobil)", + "fsIncludeCurrentBackgroundMap": "Aktuellen Hintergrund übernehmen {name}", + "fsIncludeCurrentLayers": "Aktuelle Ebenenauswahl übernehmen", "fsIncludeCurrentLocation": "Aktuelle Position einbeziehen", - "fsLayerControlToggle": "Mit der ausgeklappter Ebenensteuerung beginnen", + "fsLayerControlToggle": "Ausgeklappte Ebenensteuerung anzeigen", "fsLayers": "Ebenensteuerung aktivieren", "fsSearch": "Suchleiste aktivieren", "fsUserbadge": "Anmeldeschaltfläche aktivieren", @@ -250,9 +254,7 @@ }, "searchWikidata": "Suche auf Wikidata", "wikipediaboxTitle": "Wikipedia" - }, - "loginFailed": "Einloggen zu OpenStreetMap fehlgeschlagen", - "poweredByOsm": "Powered by OpenStreetMap" + } }, "image": { "addPicture": "Bild hinzufügen", @@ -276,39 +278,139 @@ "willBePublished": "Ihr Bild wird veröffentlicht " }, "importHelper": { - "description": "Der Import-Helfer konvertiert einen externen Datensatz in Hinweise. Der externe Datensatz muss mit einer der vorhandenen MapComplete-Ebenen übereinstimmen. Für jedes Element, das Sie in den Import-Helfer eingeben, wird ein einzelner Hinweis erstellt. Diese Hinweise werden zusammen mit den entsprechenden Objekten in diesen Karten angezeigt, um sie leicht hinzufügen zu können.", - "importFormat": "Der Hinweistext sollte folgendes Format haben, um aufgenommen zu werden:
    [Eine kleine Einführung]
    https://mapcomplete.osm.be/[themenname].html?[Parameter wie lat und lon]#import
    [alle Tags des Objekts]
    ", - "inspectDidAutoDected": "Ebene wurde automatisch ausgewählt", - "title": "Import-Helfer", - "locked": "Du benötigst mindestens {importHelperUnlock} um die Importhilfe zu benutzen", + "askMetadata": { + "downloadGeojson": "geojson herunterladen", + "giveDescription": "Bitte schreiben Sie eine kurze Beschreibung für jemanden, der die Notiz sieht. Eine gute Notiz beschreibt, was der Mitwirkende zu tun hat, z.B. Hier könnte eine Bank stehen. Wenn Sie in der Nähe sind, könnten Sie bitte überprüfen und angeben, ob die Bank existiert oder nicht? (Ein Link zu MapComplete wird automatisch hinzugefügt)", + "giveSource": "Was ist die Quelle dieser Daten? Wenn 'source' bereits als Attribut am Objekt vorhanden ist, wird dieser Wert ignoriert", + "giveWikilink": "Auf welcher Wikiseite gibt es weitere Informationen zu diesem Import?", + "intro": "Bevor Sie {count} Notizen hinzufügen, geben Sie bitte einige zusätzliche Informationen an.", + "orDownload": "Alternativ können Sie den Datensatz auch herunterladen und direkt importieren", + "shouldBeOsmWikilink": "Link zu einer Seite auf wiki.openstreetmap.org erwartet", + "shouldBeUrl": "Keine gültige URL", + "shouldNotBeHomepage": "Nein, die Homepage ist auch nicht erlaubt. Geben Sie die URL einer geeigneten Wikiseite ein, die Ihren Import dokumentiert", + "title": "Metadaten angeben" + }, + "compareToAlreadyExistingNotes": { + "completelyImported": "Alle vorgeschlagenen Punkte haben (oder hatten) bereits eine Importnotiz", + "loading": "Notizen von OSM abrufen", + "loadingFailed": "Laden von Notizen fehlgeschlagen aufgrund von {error}", + "mapExplanation": "Die roten Elemente auf der nächsten Karte sind alle Datenpunkte aus Ihrem Datensatz. Es gibt {length} Elemente in Ihrem Datensatz.", + "noPreviousNotesFound": "Keine früheren Importnotizen gefunden", + "nothingNearby": "Alle vorgeschlagenen Punkte haben keine vorherige Importnotiz in der Nähe", + "someNearby": "{hasNearby} Punkte haben eine bereits eine Importnotiz innerhalb {distance} Meter", + "title": "Mit vorhandenen Hinweisen vergleichen", + "titleLong": "Mit bereits vorhandenen 'zu-importieren'-Notizen vergleichen", + "wontBeImported": "Diese Datenpunkte werden nicht importiert und sind als rote Punkte auf der Karte unten dargestellt" + }, + "confirmProcess": { + "contactedCommunity": "Ich habe die (lokale) Community wegen dieses Imports kontaktiert", + "licenseIsCompatible": "Die Lizenz der zu importierenden Daten erlaubt es, sie in OSM zu importieren. Sie dürfen kommerziell weiterverteilt werden, mit nur minimaler Namensnennung", + "readImportGuidelines": "Ich habe die Importrichtlinien im OSM-Wiki gelesen", + "title": "Lizenz und Gemeinschaft", + "titleLong": "Haben Sie den Importvorgang durchlaufen?", + "wikipageIsMade": "Der Vorgang ist im OSM-Wiki dokumentiert (diesen Link benötigen Sie später)" + }, + "conflationChecker": { + "cacheExpired": "Der Cache ist abgelaufen", + "downloadOverpassData": "Die geladene geojson Datei von overpass herunterladen", + "importCandidatesCount": "Die {count} roten Elemente auf der folgenden Karte sind alle Ihre Importkandidaten.", + "loadedDataAge": "Geladene Daten stammen aus dem Cache und sind {age} alt", + "mapShowingNearbyIntro": "Die folgende Karte zeigt zu importierende Objekte, die ein OSM-Objekt enthalten ", + "nearbyWarn": "Die {count} roten Elemente auf der folgenden Karte werden nicht importiert!", + "nothingLoaded": "Es werden keine Elemente aus OpenStreetMap geladen, die dem aktuellen Layer {name} entsprechen", + "osmLoaded": "{count} Elemente werden aus OpenStreetMap geladen, die dem Layer {name} entsprechen.", + "setRangeToZero": "Setzen Sie den Bereich auf 0 oder 1, wenn Sie alle importieren möchten", + "states": { + "error": "Letzte Daten nicht von overpass heruntergeladen aufgrund von {error}", + "idle": "Lokalen Speicher überprüfen...", + "running": "Abfrage bei overpass...", + "unexpected": "Unerwarteter Zustand {state}" + }, + "title": "Mit vorhandenen Daten vergleichen", + "titleLive": "Live-Daten auf OSM", + "titleNearby": "Objekte in der Nähe", + "zoomIn": "Live-Daten werden ab Zoomstufe {needed} angezeigt. Die aktuelle Zoomstufe ist {current}" + }, + "createNotes": { + "creating": "{count} Notizen von {total} erstellt", + "done": "Alle {count} Notizen wurden erstellt!", + "loading": "Bitte warten, Daten werden geladen...", + "openImportViewer": "Sehen Sie den Fortschritt Ihrer Notizen im 'import_viewer'", + "title": "Notizerstellung" + }, + "gotoImportViewer": "Vorherige Importe überprüfen", + "introduction": { + "description": "Der Import-Helfer konvertiert einen externen Datensatz in Hinweise. Der externe Datensatz muss mit einer vorhandenen MapComplete-Ebene übereinstimmen. Für jedes Element, das Sie in den Importer eingeben, wird eine einzelner Hinweis erstellt. Diese Hinweise werden zusammen mit den entsprechenden Objekten in diesen Karten angezeigt, um sie leicht hinzufügen zu können.", + "importFormat": "Der Hinweistext sollte das folgende Format haben, um aufgenommen zu werden", + "title": "Einführung" + }, + "login": { + "lockNotice": "Diese Seite ist gesperrt. Zum Zugang werden {importHelperUnlock} Änderungssätze benötigt.", + "loggedInWith": "Sie sind derzeit angemeldet als {name} und haben {csCount} Änderungen vorgenommen", + "loginIsCorrect": "{name} ist das richtige Konto, mit dem die Importhinweise erstellt werden.", + "loginRequired": "Bitte anmelden, um fortzufahren", + "title": "Anmeldung", + "userAccountTitle": "Benutzerkonto auswählen" + }, + "mapPreview": { + "autodetected": "Die Ebene wurde anhand der Eigenschaften automatisch abgezogen", + "confirm": "Die Objekte befinden sich an der richtigen Stelle auf der Karte", + "mismatch": "{count} Objekte stimmen nicht mit der ausgewählten Ebene überein. Stellen Sie sicher, dass die Tags zur Angabe des Typs vorhanden sind, nämlich {tags}", + "selectLayer": "Zu welcher Ebene passt dieser Import?", + "title": "Kartenvorschau" + }, + "noteParts": { + "datasource": "Originaldaten von {source}", + "importEasily": "Diesen Punkt einfach mit MapComplete hinzufügen:", + "wikilink": "Weitere Informationen über diesen Import unter {wikilink}" + }, + "previewAttributes": { + "allAttributesSame": "Alle zu importierenden Objekte haben diesen Tag", + "inspectDataTitle": "Daten von {count} zu importierenden Objekten prüfen", + "inspectLooksCorrect": "Diese Werte sehen korrekt aus", + "someHaveSame": "{count} zu importierende Objekte haben diesen Tag, das sind {percentage}% der Gesamtanzahl", + "title": "Attribute prüfen" + }, "selectFile": { - "errNoName": "Einige Spalten haben keinen Namen", - "errNoLatOrLon": "Der Kopf? enhält weder `lat` noch `lon`", + "description": "Wähle eine .csv oder .geojson Datei um anzufangen", "errDuplicate": "Einige Spalten haben den selben Namen", + "errNoLatOrLon": "Die Kopfzeile enthält weder `lat` noch `lon`", + "errNoName": "Einige Spalten haben keinen Namen", "errNotFeatureCollection": "Die geladene JSON-Datei ist keine geojson-featurecollection", "errPointsOnly": "Die geladene JSON-Datei sollte nur Punkte enthalten", "fileFormatDescription": "Wähle eine .csv oder .geojson Datei", "fileFormatDescriptionCsv": "In der CSV-Datei sollte es jeweils eine Spalte für lat und lonmit den Koordinaten in WGS84 geben. Jedes weitere Attribut sollte in einer eigenen Spalte sein.", - "noFilesLoaded": "Keine Datei geladen", + "fileFormatDescriptionGeoJson": "In der geojson-Datei sollten nur Punkte enthalten sein. Die Eigenschaften sollten genau die Eigenschaften sein, die in OpenStreetMap verwendet werden sollen", "loadedFilesAre": "Die Datei {file} ist geladen", - "title": "Wähle eine Datei", - "description": "Wähle eine .csv oder .geojson Datei um anzufangen" + "noFilesLoaded": "Keine Datei geladen", + "title": "Datei auswählen" }, - "loginIsCorrect": "{name} ist der richtige Account um Importnotizen zu erstellen.", - "inspectLooksCorrect": "Die Werte sehen richtig aus", - "lockNotice": "Diese Seite ist gesperrt. Du brauchst die Änderungen {importHelperUnlock} bevor du die Seite öffnen kannst.", - "loggedInWith": "Du bist eingeloggt als {name} und hast {csCount} Änderungen", - "loginRequired": "Du musst eingeloggt sein um fortzufahren.", - "mapPreview": { - "title": "Kartenvorschau" + "selectTheme": { + "displayNonMatchingCount": "{length} Objekte stimmen nicht mit Voreinstellungen überein", + "intro": "Alle folgenden Themen zeigen die Importhinweise an. Die Notiz auf OpenStreetMap kann jedoch nur mit einem einzigen Thema verknüpft werden. Wählen Sie das Thema, mit dem die erstellten Notizen verknüpft werden sollen", + "misMatch": "Eigenschaft mit Schlüssel {k} hat nicht den erwarteten Wert {v}; stattdessen ist es {properties}", + "missing": "Erwartet $k}={v}, aber es fehlt komplett", + "needsTags": "{title} benötigt tags {tags}", + "noMatchingPresets": "Dieses Thema hat keine Voreinstellungen geladen. Daher werden Importe hier nicht funktionieren", + "notApplicable": "Voreinstellung {title} ist nicht anwendbar:", + "title": "Thema auswählen", + "unmatchedTitle": "Die folgenden Elemente stimmen mit keiner Voreinstellung überein" }, - "validateDataTitle": "Bestätige Daten", - "selectLayer": "Wähle eine Ebene...", - "userAccountTitle": "Wähle einen Benutzeraccount" + "testMode": "Testmodus - Notizen werden nicht importiert", + "title": "Import-Helfer" }, "importInspector": { "title": "Importhinweise überprüfen und verwalten" }, + "importLayer": { + "alreadyMapped": "Es gibt bereits einen anderen {title} auf der Karte - dieser Punkt ist ein Duplikat", + "description": "Eine Ebene, die Einträge für {title} importiert", + "importButton": "import_button({layerId}, _tags, Ich habe hier ein(en) {title} gefunden - Zur Karte hinzufügen,./assets/svg/addSmall.svg,,,id)", + "importHandled": "
    Dieses Objekt wurde behandelt! Vielen Dank für Ihre Bemühungen
    ", + "layerName": "Möglicher {title}", + "notFound": "Ich konnte {title} nicht finden - entferne es", + "popupTitle": "Möglicher {title}" + }, "index": { "#": "Dieser Text wird über die Thema-Auswahlschaltfläche gezeigt, wenn kein Thema geladen ist", "featuredThemeTitle": "Diese Woche im Blickpunkt", @@ -343,51 +445,151 @@ "zoomInFurther": "Weiter vergrößern, um die Verschiebung zu bestätigen" }, "multi_apply": { - "autoApply": "Wenn Sie die Attribute {attr_names} ändern, werden diese Attribute automatisch auch auf {count} anderen Objekten geändert" + "autoApply": "Wenn Sie die Attribute {attr_names} ändern, diese Änderung automatisch auch auf {count} andere Objekte angewendet" + }, + "notes": { + "addAComment": "Füge einen Kommentar hinzu", + "addComment": "Kommentieren", + "addCommentAndClose": "Kommentieren und Schließe", + "addCommentPlaceholder": "Einen Kommentar hinzufügen...", + "anonymous": "Anonymer Benutzer", + "closeNote": "Schließe Notiz", + "createNote": "Erstelle eine neue Notiz", + "createNoteIntro": "Ist etwas falsch oder fehlt auf der Karte? Erstellen Sie hier eine Notiz. Diese werden von Freiwilligen überprüft.", + "createNoteTitle": "Erstelle hier eine neue Notiz", + "disableAllNoteFilters": "Deaktiviere alle Filter", + "isClosed": "Dieser Hinweis wurde geklärt", + "isCreated": "Deine Notiz wurde erstellt!", + "loginToAddComment": "Einloggen um zu Kommentieren", + "loginToAddPicture": "Einloggen um ein Bild hinzuzufügen", + "loginToClose": "Einloggen um diesen Hinweis zu schließen", + "noteIsPublic": "Es wird für alle sichtbar sein", + "noteLayerDoEnable": "Aktivieren Sie die Ebene der Hinweise", + "noteLayerHasFilters": "Einige Notizen können durch einen Filter versteckt sein", + "noteLayerNotEnabled": "Die Ebene der Hinweise ist nicht aktiviert. Die Ebene muss aktiviert sein, um einen neuen Hinweis hinzuzufügen", + "notesLayerMustBeEnabled": "Die 'Hinweis'-Ebene ist deaktiviert. Aktivieren Sie sie, um einen Hinweis hinzuzufügen", + "reopenNote": "Hinweis wieder öffnen", + "reopenNoteAndComment": "Hinweis wieder öffnen und kommentieren", + "textNeeded": "Geben Sie einen beschreibenden Text ein, um einen Hinweis zu erstellen", + "typeText": "Geben Sie einen Text ein, um einen Kommentar hinzuzufügen", + "warnAnonymous": "Sie sind nicht eingeloggt. Wir sind nicht in der Lage, Sie zu kontaktieren, um Ihr Problem zu lösen." }, "privacy": { - "editing": "Wenn Sie eine Änderung an der Karte vornehmen, wird diese Änderung auf OpenStreetMap aufgezeichnet und ist für jeden öffentlich zugänglich. Ein mit MapComplete vorgenommener Änderungssatz enthält die folgenden Daten:
    • Die von Ihnen vorgenommenen Änderungen
    • Ihr Benutzername
    • Wann diese Änderung vorgenommen wurde
    • Das Thema, das Sie bei der Änderung verwendet haben
    • Die Sprache der Benutzeroberfläche
    • Eine Angabe darüber, wie nah Sie an geänderten Objekten waren. Andere Kartierer können diese Informationen nutzen, um festzustellen, ob eine Änderung auf Basis einer Vor-Ort Erkundung oder einer Fernerkundung vorgenommen wurde
    Ausführliche Informationen finden Sie in den Datenschutzbestimmungen auf OpenStreetMap.org. Wir möchten Sie daran erinnern, dass Sie bei der Anmeldung einen fiktiven Namen verwenden können.", + "editing": "Wenn Sie Änderungen an der Karte vornehmen, werden diese auf OpenStreetMap gespeichert und sind für jeden öffentlich zugänglich. Ein mit MapComplete erstellter Änderungssatz enthält folgende Daten:
    • Die von Ihnen vorgenommenen Änderungen
    • Ihren Benutzernamen
    • Den Zeitpunkt Ihrer Änderungen
    • Das MapComplete-Thema, das Sie bei Ihren Änderungen verwendet haben
    • Die Sprache Ihrer Benutzeroberfläche
    • Eine Angabe darüber, wie nah Sie an geänderten Objekten waren. Andere Kartierer können diese Informationen nutzen, um festzustellen, ob eine Änderung auf Basis einer Vor-Ort Erkundung oder einer Fernerkundung vorgenommen wurde
    Ausführliche Informationen finden Sie in den Datenschutzbestimmungen auf OpenStreetMap.org. Wir möchten Sie daran erinnern, dass Sie bei der Anmeldung einen fiktiven Namen verwenden können.", "editingTitle": "Ihre Änderungen", - "geodata": "Wenn MapComplete Ihre Standortdaten erhält, verbleiben Ihre Daten zum aktuellen Standort und zuvor besuchter Orte auf Ihrem Gerät. Ihre Standortdaten werden niemals automatisch an eine andere Stelle gesendet - es sei denn, eine Funktion gibt eindeutig etwas anderes an.", + "geodata": "Wenn MapComplete Ihre aktuellenStandortdaten ermittelt, verbleiben diese wie auch zuvor ermittelte Standorte auf Ihrem Gerät. Ihre Standortdaten werden niemals automatisch an eine andere Stelle gesendet - es sei denn, eine Funktion gibt eindeutig etwas anderes an.", "geodataTitle": "Ihr Standort", "intro": "Privatsphäre ist wichtig - sowohl für den Einzelnen als auch für die Gesellschaft. MapComplete versucht, Ihre Privatsphäre so weit wie möglich zu respektieren - bis zu dem Punkt, an dem kein lästiger Cookie-Banner mehr nötig ist. Dennoch möchten wir Sie darüber informieren, welche Informationen gesammelt und weitergegeben werden, unter welchen Umständen und warum diese Kompromisse gemacht werden.", "miscCookies": "MapComplete integriert verschiedene andere Dienste, insbesondere um Bilder von Objekten zu laden. Bilder werden auf verschiedenen Servern von Drittanbietern gehostet, die möglicherweise eigene Cookies setzen.", "miscCookiesTitle": "Andere Cookies", "surveillance": "Da Sie die Datenschutzbestimmungen lesen, ist Ihnen der Datenschutz wahrscheinlich wichtig - uns auch! Wir haben sogar ein Thema gemacht, das Überwachungskameras zeigt. Zögern Sie nicht, sie alle zu mappen!", "title": "Datenschutzbestimmungen", - "whileYoureHere": "Ist Ihnen die Privatsphäre wichtig?", - "trackingTitle": "Statistische Daten" + "tracking": "Um einen Einblick zu bekommen, wer unsere Website besucht, werden einige technische Informationen gesammelt. Dazu gehören das Land, aus dem Sie die Webseite besucht haben, die Webseite, die Sie auf MapComplete verwiesen hat, der Typ Ihres Geräts und die Bildschirmgröße. Ein Cookie wird auf Ihrem Gerät platziert, um anzuzeigen, dass Sie MapComplete heute bereits besucht haben. Diese Daten sind nicht detailliert genug, um Sie persönlich zu identifizieren. Diese Statistiken sind nur in aggregierter Form öffentlich für jedermann zugänglich", + "trackingTitle": "Statistische Daten", + "whileYoureHere": "Ist Ihnen die Privatsphäre wichtig?" }, "professional": { - "indexPage": { - "button": "Erfahren Sie mehr über unsere Dienstleistungen", - "hook": "Benötigen Sie professionelle Unterstützung?", - "hookMore": "Wir können bei der Erstellung von Umfragen, Datenimporten und OpenStreetMap-Beratung helfen." - }, "aboutMc": { + "internalUse": { + "intro": "Sobald die Daten in OpenStreetMap sind, werden Sie sie wahrscheinlich auch nutzen wollen. Ihr MapComplete-Thema kann eine praktische export-Schaltfläche haben, mit der Sie die Daten in vielen offenen Formaten herunterladen können, die in QGis, ArcGis, Excel, LibreOffice-calc, ... verwendbar sind.

    Jemand mit grundlegenden Tabellenkalkulationskenntnissen kann so leicht Diagramme und Einblicke über die Daten erstellen, während die GIS-Experten in Ihrer Organisation leicht mit diesen Daten in ihrer bevorzugten Anwendung arbeiten können.

    Wenn eine automatisierte Einrichtung benötigt wird, ist eine frei zu verwendende, von der Gemeinschaft betriebene API verfügbar.

    ", + "title": "Verwendung der Daten in internen Prozessen" + }, "layers": { + "intro": "

    MapComplete verfügt über ein leistungsfähiges Vorlagen-System, das es ermöglicht, schnell eine Karte zu erstellen, die genau die Objekte zeigt, die Sie benötigen, und die relevanten Attribute in den Popups anzuzeigen.

    Diese Daten können direkt von OpenStreetMap geholt werden, MapComplete kann jedoch auch externe Datensätze verwenden - z.B. um OpenStreetMap mit einem anderen Datensatz zu vergleichen oder um Daten anzuzeigen, die nicht für OpenStreetMap geeignet sind (geplante Aktivitäten, Statistiken, ...)

    ", "title": "Welche Daten können mit MapComplete gezeigt werden?" }, "survey": { + "intro": "MapComplete ist ein einfach zu bedienendes Umfrage Werkzeug. Es ist ideal, um das Notwendige in ein paar Klicks zu sammeln, sowohl auf dem Desktop und auf dem Handy. Diese Daten werden direkt in OpenStreetMap eingebracht.

    Wir können ein maßgeschneidertes Umfragetool einrichten, das genau die Daten abfragt, die Sie zukunftssicher benötigen.

    Haben Sie einen Datensatz, der (neu) geprüft werden muss? Das ist der perfekte Zeitpunkt, um auf OpenStreetMap umzusteigen. MapComplete kann Ihren Datensatz und OpenStreetMap gleichzeitig anzeigen, so dass es einfacher ist, alle Standorte zu besuchen und zu sehen, was die Gemeinschaft bereits beigetragen hat.

    \n", "title": "Umfragemöglichkeiten" }, + "text0": "Wenn ein bestehendes MapComplete Thema das ist, was Sie brauchen, fühlen Sie sich frei, es zu benutzen oder betten Sie es auf Ihrer Website ein. Das Einbetten der öffentlichen Themen ist kostenlos und wird es immer sein.", + "text1": "Brauchen Sie andere Daten, aber das Thema existiert noch nicht? Die MapComplete-Entwickler können es für Sie zusammenstellen für einen fairen Betrag. Kontaktieren Sie uns über email, github oder ;senden Sie eine Nachricht über osm.org", + "text2": "Wenn Sie noch unsicher sind, finden Sie im Folgenden eine Übersicht über die Möglichkeiten. Außerdem werden einige häufig gestellte Fragen beantwortet", "title": "Benutze MapComplete in deinem Organisation" }, "aboutOsm": { - "license": { - "title": "Die Lizenz" - }, "aboutOsm": { - "title": "Was ist OpenStreetMap?", - "li3": "und vieles, vieles mehr…" - }, - "vandalism": { - "title": "Gibt es Vandalismus?" + "intro": "OpenStreetMap ist eine gemeinsame, globale Datenbank, die von Freiwilligen aufgebaut wird. Alle Geodaten können zu OpenStreetMap beigetragen werden, solange sie vor Ort verifiziert werden können.
    OpenStreetMap ist zu einem sehr breiten und detaillierten Datensatz herangewachsen, da es Daten über Tausende von Objektkategorien enthält. Ein einzelnes Objekt kann auch eine Menge Attribute haben, die viele Nuancen mit sich bringen, z. B:", + "li0": "Straßen haben eine Geometrie, können aber auch Informationen enthalten über die Höchstgeschwindigkeit, die Oberfläche, ob sie beleuchtet sind, ihren Namen, einen Link zu Wikipedia, einen Link zu dem, wonach sie benannt sind, welche Wander-, Rad- und Busrouten dort verlaufen, …", + "li1": "Geschäfte und andere Einrichtungen enthalten Öffnungszeiten, eine Telefonnummer, einen Link zur Website, die unterstützten Zahlungsmethoden, das Angebot, die angebotenen Dienstleistungen, …", + "li2": "Die Toiletten besitzen Informationen über die Zugänglichkeit für Rollstuhlfahrer, einen Wickeltisch, die Notwendigkeit einer Bezahlung, …", + "li3": "und vieles, vieles mehr…", + "title": "Was ist OpenStreetMap?" }, "benefits": { + "intro": "Es kann sehr schwer sein, den eigenen Datensatz hinter sich zu lassen, da der Aufbau dieses Datensatzes oft viel Zeit und Mühe gekostet hat.
    Die Vorteile des Wechsels zu OSM sind jedoch enorm:", + "li0": "Sie sind beim Sammeln und Pflegen dieses Datenbestands nicht mehr allein - eine ganze Gemeinschaft steht Ihnen zur Seite", + "li1": "Ihre Daten erreichen ein größeres Publikum als je zuvor über Bing Maps, Apple Maps, Facebook, Instagram, Pokemon Go, OsmAnd, Organic Maps, Maps.me, Mapbox, Komoot, fast alle Fahrrad-Applikationen, …", + "li2": "Viele Regierungsorganisationen und Kommunen nutzen OpenStreetMap auch auf ihren Webseiten", "title": "Vorteile des OSM-Ökosystem" + }, + "license": { + "intro": "OpenStreetMap ist unter der Open Database License lizenziert. Der vollständige Copyright-Text lässt sich wie folgt zusammenfassen:", + "li0": "Ein Produkt, das OpenStreetMap-Daten verwendet, muss eine Quellenangabe enthalten.", + "li1": "OpenStreetMap-Daten müssen offen bleiben. Dies bedeutet, dass die Daten einer Karte, die OpenStreetMap-Daten enthält, erneut kopiert werden können.", + "outro": "Die Lizenz hat einige Auswirkungen, die im Folgenden erläutert werden.", + "title": "Die Lizenz" + }, + "vandalism": { + "intro": "Da jeder die Daten bearbeiten kann, ist es durchaus möglich, dass eine böswillige Änderung vorgenommen wird. Dies ist jedoch aus mehreren Gründen extrem selten:", + "li0": "Die technische Hürde, Änderungen vorzunehmen, ist hoch", + "li1": "eine kleine böswillige Veränderung hat nur geringe Auswirkungen und ist daher für einen Vandalen wenig lohnend", + "li2": "eine Änderung, die sich stark auswirkt, wird schnell bemerkt und rückgängig gemacht, da so viele Menschen diese Daten nutzen", + "li3": "Alle Änderungen werden nachverfolgt und an einen einzelnen Benutzer gebunden. Ein Wiederholungstäter wird schnell gesperrt", + "li4": "In Belgien (und einigen anderen Ländern) wird der erste Beitrag eines neuen Verfassers systematisch überprüft und bei Bedarf korrigiert.", + "title": "Gibt es Vandalismus?" } - } + }, + "drawbacks": { + "intro": "Der Beitritt zu dieser Gemeinschaft hat zwar enorme Vorteile, aber es gibt auch ein paar Dinge, die man sorgfältig bedenken sollte.", + "licenseNuances": { + "intro": "OpenStreetMap ist unter der Open Database License lizenziert, die besagt, dass:", + "li0": "Alle Daten können für jeden Zweck wiederverwendet werden - auch für kommerzielle Zwecke", + "li1": "Anwendungen oder Produkte, die OpenStreetMap verwenden, sollten einen deutlich sichtbaren Urheberrechtshinweis enthalten", + "li2": "Jeder Datensatz oder jedes Produkt, das OpenStreetMap-Daten enthält, muss ebenfalls unter ODbL veröffentlicht werden, einschließlich Änderungen an diesem Datensatz und in einem verwendbaren Format.", + "outro": "Dies hat einige Auswirkungen, die für einige Anwendungsfälle zu berücksichtigen sind, wie im Folgenden erläutert", + "title": "Implikationen der ODbL: einige Anwendungsfälle", + "usecaseGatheringOpenData": { + "intro": "MapComplete ist eine hervorragende Möglichkeit, offene Daten zu erstellen, auch für Regierungen. Standardmäßig sind diese Daten unter der ODbL frei weiterverteilbar. Wenn jedoch die Anforderung besteht, die gesammelten Daten unter einer Public Domain-Lizenz zu veröffentlichen (bei der alle Rechte der Öffentlichkeit gewährt werden und keine Zuschreibung erforderlich ist), ist die ODbL zu restriktiv. In diesem Fall kann man die Mitwirkenden auffordern, die Daten als gemeinfrei einzustellen (z. B. indem man sie im mapcomplete-Thema darüber informiert).", + "title": "Sammeln offener Daten" + }, + "usecaseMapDifferentSources": { + "intro": "Man könnte zum Beispiel eine Karte mit allen Bänken in einer Stadt erstellen, die auf den von OpenStreetMap bekannten Bänken basiert. Diese gedruckte Karte muss einen klaren Hinweis enthalten, dass die Kartendaten auf OpenStreetMap basieren. Stellt der Kartenmacher fest, dass in einem bestimmten Gebiet Bänke fehlen, und fügt diese auf der gedruckten Karte hinzu, sind die Daten zu den fehlenden Bänken automatisch auch offene Daten. Das bedeutet, dass ein OpenStreetMap-Mitwirkender die gedruckte Karte nehmen und sie verwenden darf, um die fehlenden Bänke wieder in OpenStreetMap einzufügen. Dieser Mitwirkende hat auch das Recht, den Datensatz der fehlenden Bänke anzufordern, der ebenfalls bereitgestellt werden sollte.

    Natürlich kann eine Karte nur mit Bänken langweilig sein. Der Kartenersteller könnte auch beschließen, eine Ebene mit Geschäften hinzuzufügen, die möglicherweise von einem anderen Geodatenanbieter unter einer anderen Lizenz bezogen werden. Dies ist zulässig, wenn auf der Karte deutlich angegeben wird, dass die Bänke von OSM (unter ODBL) stammen und die Geschäfte eine andere Quelle haben (eventuell mit einem \"All rights reserved\"). Wenn der Kartenersteller z. B. feststellt, dass OSM über ausgezeichnete Daten zu Bänken in einem Teil der Stadt verfügt und der Closed-Source-Anbieter über ausgezeichnete Daten zu Bänken in einem anderen Teil der Stadt, könnte die Zusammenführung dieser Datensätze zu einem einzigen problematisch sein:

    ", + "li0": "die offene Lizenz würde verlangen, dass die Modifikationen offen wiederveröffentlicht werden…", + "li1": "...wohingegen die All-Rights-Reserved-Lizenz dies untersagen würde.", + "outro": "Folglich ist diese Art der Vermischung nicht erlaubt", + "title": "Erstellung einer Karte aus verschiedenen Quellen" + } + }, + "title": "Ein paar Nachteile, die Sie beachten sollten", + "unsuitedData": { + "intro": "Die Grundregel für OpenStreetMap ist, dass alle Daten vor Ort überprüfbar und einigermaßen dauerhaft sein müssen. Dies bedeutet, dass einige Daten nicht direkt an OpenStreetMap gesendet werden können - aber es gibt einige Umgehungsmöglichkeiten.", + "li0": "Subjektive Daten (wie z. B. Bewertungen) sind für OpenStreetMap nicht geeignet. MapComplete hat jedoch eine Integration mit Mangrove.reviews, einer offen lizenzierten Bewertungswebsite", + "li1": "Veranstaltungen werden nicht erfasst, ebenso wenig wie Straßenarbeiten, die nur wenige Tage dauern.", + "li2": "Zeitliche Daten (z.B. Statistiken zur Luftqualität, Verkehrsintensität, ...) können nicht auf OpenStreetMap gespeichert werden, da sie von einem Freiwilligen nur schwer zu überprüfen sind. Wenn diese Daten anderswo verfügbar sind, können sie dennoch in MapComplete als zusätzliche Ebene visualisiert werden.", + "title": "Nicht für OpenStreetMap geeignete Daten" + } + }, + "indexPage": { + "button": "Mehr über unsere Dienste erfahren", + "hook": "Benötigen Sie professionelle Unterstützung?", + "hookMore": "Wir können bei der Erstellung von Umfragen, Datenimporten und OpenStreetMap-Beratung helfen" + }, + "intro": "Der Entwickler von MapComplete bietet professionelle Unterstützung an. Dieses Dokument skizziert einige der Möglichkeiten, häufige Fragen und die Grenzen von MapComplete", + "osmTitle": "Was können OpenStreetMap und MapComplete für Ihre Organisation tun?", + "services": { + "intro": "Der Entwickler von MapComplete kann Ihnen mit den folgenden Dienstleistungen helfen:", + "li0": "Einrichten eines auf Ihren Bedarf zugeschnittenen Themas", + "li1": "Hilfe bei der Einrichtung des internen Datenflusses zur Integration von OpenStreetMap", + "li2": "Schulung über die Bereitstellung von Daten mit MapComplete", + "li3": "Fortbildung (z.B. für das GIS-Team), wie man erweiterte Daten zu OpenStreetMap hinzufügt", + "li4": "Schulung zum Herunterladen gefilterter Daten von OpenStreetMap", + "outro": "Diese Dienstleistungen werden zu wettbewerbsfähigen Preisen angeboten. Ein einfaches Thema ohne zusätzliche Unterstützung kann für nur 2.000 € eingerichtet werden, zuzüglich geringer jährlicher Hosting-Kosten.", + "title": "MapComplete-Dienste" + }, + "text0": "

    Die Pflege eines Satzes aktueller Geodaten ist schwierig, fehleranfällig und teuer.
    Zu allem Überfluss sammeln viele Organisationen dieselben Daten unabhängig voneinander - was zu doppelten Anstrengungen, nicht standardisierten Datenformaten und vielen unvollständigen, ungepflegten Datensätzen führt.

    Gleichzeitig gibt es eine riesige Gemeinschaft, die viele Geodaten in einer gemeinsamen, globalen und standardisierten Datenbank sammelt - nämlich OpenStreetMap.org.

    ", + "text1": "

    MapComplete ist der Editor, der das Einbringen von Daten in OpenStreetMap einfach macht.

    ", + "title": "Professionelle Unterstützung mit MapComplete" }, "reviews": { "affiliated_reviewer_warning": "(Partner-Rezension)", @@ -414,36 +616,72 @@ "splitTitle": "Wählen Sie auf der Karte aus, wo die Straße geteilt werden soll" }, "translations": { - "activateButton": "Bei der Übersetzung von MapComplete helfen", - "completeness": "Die Übersetzungen für {theme} in {language} liegen bei {percentage}%: {translated} Zeichenfolgen von {total} sind übersetzt", + "activateButton": "MapComplete übersetzen", + "completeness": "Die Übersetzungen für {theme} in {language} ist zu {percentage}% vollständig: {translated} Zeichenfolgen von {total} sind übersetzt", "deactivate": "Schaltflächen für die Übersetzung deaktivieren", "help": "Klicken Sie auf das 'translate'-Symbol neben einer Zeichenfolge, um einen Text einzugeben oder zu aktualisieren. Dazu benötigen Sie einen Weblate-Account. Erstellen Sie einen mit Ihrem OSM-Benutzernamen, um den Übersetzungsmodus automatisch freizuschalten.", - "isTranslator": "Der Übersetzungsmodus ist aktiv, da Ihr Benutzername mit dem Namen eines früheren Übersetzers übereinstimmt" + "isTranslator": "Der Übersetzungsmodus ist aktiv, da Ihr Benutzername mit dem Namen eines früheren Übersetzers übereinstimmt", + "missing": "{count} unübersetzte Zeichenfolgen", + "notImmediate": "Die Übersetzungen werden nicht direkt aktualisiert. Dies dauert in der Regel ein paar Tage" }, - "notes": { - "addCommentPlaceholder": "Add a comment...", - "anonymous": "Anonymer Benutzer", - "closeNote": "Schließe Notiz", - "disableAllNoteFilters": "Deaktiviere alle Filter", - "isCreated": "Deine Notiz wurde erstellt!", - "noteIsPublic": "Es wird für alle sichtbar sein", - "addAComment": "Füge einen Kommentar hinzu", - "addComment": "Kommentieren", - "createNote": "Erstelle eine neue Notiz", - "createNoteTitle": "Erstelle hier eine neue Notiz", - "loginToClose": "Einloggen um die Notiz zu schließen", - "isClosed": "Diese Notiz ist geklärt", - "loginToAddComment": "Einloggen um zu Kommentieren", - "loginToAddPicture": "Einloggen um ein Bild hinzuzufügen", - "noteLayerDoEnable": "Aktiviere die Ebene \"showing notes\"", - "noteLayerNotEnabled": "Die Ebene \"showing notes\" ist nicht aktiviert. Die Ebene muss aktiviert sein um eine Notiz hinzuzufügen", - "noteLayerHasFilters": "Einige Notizen können durch einen Filter versteckt sein", - "addCommentAndClose": "Kommentieren und Schließe" - }, - "importLayer": { - "popupTitle": "Möglicher {title}", - "layerName": "Möglicher {title}", - "notFound": "Ich konnte {title} nicht finden - entferne es", - "description": "Eine Ebene, die Einträge für {title} importiert" + "validation": { + "color": { + "description": "Farbe oder Hexcode" + }, + "date": { + "description": "Ein Datum, beginnend mit der Jahreszahl" + }, + "decimal": { + "description": "Eine Zahl" + }, + "direction": { + "description": "Eine Himmelsrichtung" + }, + "email": { + "description": "E-Mail Adresse", + "feedback": "Dies ist keine gültige E-Mail Adresse", + "noAt": "Eine E-Mail-Adresse sollte ein @ enthalten" + }, + "float": { + "description": "eine Zahl", + "feedback": "Dies ist keine Zahl" + }, + "int": { + "description": "eine ganze Zahl" + }, + "nat": { + "description": "eine positive, ganze Zahl oder Null", + "mustBePositive": "Diese Zahl sollte positiv sein", + "mustBeWhole": "Es sind nur ganze Zahlen erlaubt", + "notANumber": "Eine Nummer eingeben" + }, + "opening_hours": { + "description": "Öffnungszeiten" + }, + "pfloat": { + "description": "eine positive Zahl" + }, + "phone": { + "description": "eine Telefonnummer", + "feedback": "Dies ist keine gültige Telefonnummer" + }, + "pnat": { + "description": "eine positive, ganze Zahl", + "noZero": "Null ist nicht erlaubt" + }, + "string": { + "description": "ein Stück Text" + }, + "text": { + "description": "ein Stück Text" + }, + "tooLong": "Der Text ist zu lang, es sind maximal 255 Zeichen erlaubt. Sie haben jetzt {count} Zeichen", + "url": { + "description": "Link zu einer Website", + "feedback": "Dies ist keine gültige Webadresse" + }, + "wikidata": { + "description": "Eine Wikidata-Kennung" + } } } diff --git a/langs/en.json b/langs/en.json index ea8056964..4b6f74a0e 100644 --- a/langs/en.json +++ b/langs/en.json @@ -19,7 +19,7 @@ "loading": "Inspecting properties to check if this feature can be deleted.", "loginToDelete": "You must be logged in to delete a point", "notEnoughExperience": "This point was made by someone else.", - "onlyEditedByLoggedInUser": "This point has only be edited by yourself, you can safely delete it.", + "onlyEditedByLoggedInUser": "This point has only been edited by yourself, you can safely delete it.", "partOfOthers": "This point is part of some way or relation and can not be deleted directly.", "readMessages": "You have unread messages. Read these before deleting a point - someone might have feedback", "reasons": { @@ -119,6 +119,7 @@ "title": "Download visible data", "uploadGpx": "Upload your track to OpenStreetMap" }, + "error": "Something went wrong", "example": "Example", "examples": "Examples", "fewChangesBefore": "Please, answer a few questions of existing points before adding a new point.", @@ -151,6 +152,7 @@ "next": "Next", "noNameCategory": "{category} without a name", "noTagsSelected": "No tags selected", + "notValid": "Select a valid value to continue", "number": "number", "oneSkippedQuestion": "One question is skipped", "openStreetMapIntro": "

    An Open Map

    One that everyone can use and edit freely. A single place to store all geo-info. Different, small, incompatible and outdated maps are not needed anywhere.

    OpenStreetMap is not the enemy map. The map data can be used freely (with attribution and publication of changes to that data). Everyone can add new data and fix errors. This website uses OpenStreetMap. All the data is from there, and your answers and corrections are used all over.

    Many people and apps already use OpenStreetMap: Organic Maps, OsmAnd, but also the maps at Facebook, Instagram, Apple-maps and Bing-maps are (partly) powered by OpenStreetMap.

    ", @@ -201,6 +203,8 @@ "sharescreen": { "addToHomeScreen": "

    Add to your home screen

    You can easily add this website to your smartphone home screen for a native feel. Click the 'Add to home screen' button in the URL bar to do this.", "copiedToClipboard": "Link copied to clipboard", + "downloadCustomTheme": "Download the configuration for this theme", + "downloadCustomThemeHelp": "An experienced contributor can use this file to improve your theme", "editThemeDescription": "Add or change questions to this map theme", "editThisTheme": "Edit this theme", "embedIntro": "

    Embed on your website

    Please, embed this map into your website.
    We encourage you to do it - you don't even have to ask permission.
    It is free, and always will be. The more people are using this, the more valuable it becomes.", @@ -276,17 +280,81 @@ "willBePublished": "Your picture will be published " }, "importHelper": { - "allAttributesSame": "All features to import have this tag", - "description": "The import helper converts an external dataset to notes. The external dataset must match one of the existing MapComplete layers. For every item you put in the importer, a single note will be created. These notes will be shown together with the relevant features in these maps to easily add them.", - "importFormat": "A text in a note should have the following format in order to be picked up:
    [A bit of introduction]
    https://mapcomplete.osm.be/[themename].html?[parameters such as lat and lon]#import
    [all tags of the feature]
    ", - "inspectDataTitle": "Inspect data of {count} features to import", - "inspectDidAutoDected": "Layer was chosen automatically", - "inspectLooksCorrect": "These values look correct", - "lockNotice": "This page is locked. You need {importHelperUnlock} changesets before you can access here.", - "locked": "You need at least {importHelperUnlock} to use the import helper", - "loggedInWith": "You are currently logged in as {name} and have made {csCount} changesets", - "loginIsCorrect": "{name} is the correct account to create the import notes with.", - "loginRequired": "You have to be logged in to continue", + "askMetadata": { + "downloadGeojson": "Download geojson", + "giveDescription": "Please, write a small description for someone who sees the note. A good note describes what the contributor has to do, e.g; There might be a bench here. If you are around, could you please check and indicate if the bench exists or not? (A link to MapComplete will be added automatically)", + "giveSource": "What is the source of this data? If 'source' is set in the feature, this value will be ignored", + "giveWikilink": "On what wikipage can one find more information about this import?", + "intro": "Before adding {count} notes, please provide some extra information.", + "orDownload": "Alternatively, you can download the dataset to import directly", + "shouldBeOsmWikilink": "Expected a link to a page on wiki.openstreetmap.org", + "shouldBeUrl": "Not a valid URL", + "shouldNotBeHomepage": "Nope, the home page isn't allowed either. Enter the URL of a proper wikipage documenting your import", + "title": "Set metadata" + }, + "compareToAlreadyExistingNotes": { + "completelyImported": "All of the proposed points have (or had) an import note already", + "loading": "Fetching notes from OSM", + "loadingFailed": "Loading notes failed due to {error}", + "mapExplanation": "The red elements on the next map are all the data points from your dataset. There are {length} elements in your dataset.", + "noPreviousNotesFound": "No previous import notes found", + "nothingNearby": "None of the proposed points have an import note nearby", + "someNearby": "{hasNearby} points do have an already existing import note within {distance} meter", + "title": "Compare with existing notes", + "titleLong": "Compare with already existing 'to-import'-notes", + "wontBeImported": "These data points will not be imported and are shown as red dots on the map below" + }, + "confirmProcess": { + "contactedCommunity": "I did contact the (local) community about this import", + "licenseIsCompatible": "The license of the data to import allows it to be imported into OSM. They are allowed to be redistributed commercially, with only minimal attribution", + "readImportGuidelines": "I have read the import guidelines on the OSM wiki", + "title": "License and community", + "titleLong": "Did you go through the import process?", + "wikipageIsMade": "The process is documented on the OSM-wiki (you'll need this link later)" + }, + "conflationChecker": { + "cacheExpired": "Cache was expired", + "downloadOverpassData": "Download the loaded geojson from overpass", + "importCandidatesCount": "The {count} red elements on the following map are all your import candidates.", + "loadedDataAge": "Loaded data is from the cache and is {age} old", + "mapShowingNearbyIntro": "The following map shows features to import which have an OSM-feature within ", + "nearbyWarn": "The {count} red elements on the following map will not be imported!", + "nothingLoaded": "No elements are loaded from OpenStreetMap which match the current layer {name}", + "osmLoaded": "{count} elements are loaded from OpenStreetMap which match the layer {name}.", + "reloadTheCache": "Clear the cache and query overpass again", + "setRangeToZero": "Set the range to 0 or 1 if you want to import them all", + "states": { + "error": "Could not load latest data from overpass due to {error}", + "idle": "Checking local storage...", + "running": "Querying overpass...", + "unexpected": "Unexpected state {state}" + }, + "title": "Compare with existing data", + "titleLive": "Live data on OSM", + "titleNearby": "Nearby features", + "zoomIn": "The live data is shown if the zoomlevel is at least {needed}. The current zoom level is {current}" + }, + "createNotes": { + "creating": "Created {count} notes out of {total}", + "done": "All {count} notes have been created!", + "loading": "Hang on while we are loading...", + "openImportViewer": "Inspect the progress of your notes in the 'import_viewer'", + "title": "Note creation" + }, + "gotoImportViewer": "Inspect your previous imports", + "introduction": { + "description": "The import helper converts an external dataset to notes. The external dataset must match one of the existing MapComplete layers. For every item you put in the importer, a single note will be created. These notes will be shown together with the relevant features in these maps to easily add them.", + "importFormat": "A text in a note should have the following format in order to be picked up", + "title": "Introduction" + }, + "login": { + "lockNotice": "This page is locked. You need {importHelperUnlock} changesets before you can access here.", + "loggedInWith": "You are currently logged in as {name} and have made {csCount} changesets", + "loginIsCorrect": "{name} is the correct account to create the import notes with.", + "loginRequired": "You have to be logged in to continue", + "title": "Login", + "userAccountTitle": "Select user account" + }, "mapPreview": { "autodetected": "The layer was automatically deducted based on the properties", "confirm": "The features are on the right location on the map", @@ -294,6 +362,18 @@ "selectLayer": "Which layer does this import match with?", "title": "Map preview" }, + "noteParts": { + "datasource": "Original data from {source}", + "importEasily": "Add this point easily with MapComplete:", + "wikilink": "More information about this import can be found at {wikilink}" + }, + "previewAttributes": { + "allAttributesSame": "All features to import have this tag", + "inspectDataTitle": "Inspect data of {count} features to import", + "inspectLooksCorrect": "These values look correct", + "someHaveSame": "{count} features to import have this tag, this is {percentage}% of the total", + "title": "Inspect attributes" + }, "selectFile": { "description": "Select a .csv or .geojson file to get started", "errDuplicate": "Some columns have the same name", @@ -308,11 +388,19 @@ "noFilesLoaded": "No file is currently loaded", "title": "Select file" }, - "selectLayer": "Select a layer...", - "someHaveSame": "{count} features to import have this tag, this is {percentage}% of the total", - "title": "Import helper", - "userAccountTitle": "Select user account", - "validateDataTitle": "Validate data" + "selectTheme": { + "displayNonMatchingCount": "{length} objects dont match any presets", + "intro": "All of the following themes will show the import notes. However, the note on OpenStreetMap can link to only one single theme. Choose which theme that the created notes will link to", + "misMatch": "Property with key {k} does not have expected value {v}; instead it is {properties}", + "missing": "Expected $k}={v}, but it is completely missing", + "needsTags": "{title} needs tags {tags}", + "noMatchingPresets": "This theme has no presets loaded. As a result, imports won't work here", + "notApplicable": "Preset {title} is not applicable:", + "title": "Select a theme", + "unmatchedTitle": "The following elements don't match any of the presets" + }, + "testMode": "Testmode - won't actually import notes", + "title": "Import helper" }, "importInspector": { "title": "Inspect and manage import notes" @@ -418,7 +506,7 @@ "title": "Survey possibilities" }, "text0": "If an existing MapComplete theme is what you, feel free to use it or embed it on your website. Embedding the public themes is free and always will be.", - "text1": "Do you need some other data, but does the theme not exist yet? The MapComplete-developers can build it for you on a decent budget. Get in touch via email, github or send a message via osm.org", + "text1": "Do you need some other data, but does the theme not exist yet? The MapComplete-developers can build it for you on a decent budget. Get in touch via email, github or send a message via osm.org", "text2": "If you still feel unsure, the possibilities are outlined below. Additionally, some common questions are answered", "title": "Using MapComplete in your organization" }, @@ -532,6 +620,7 @@ }, "translations": { "activateButton": "Help to translate MapComplete", + "allMissing": "No translations yet", "completeness": "Translations for {theme} in {language} are at {percentage}%: {translated} strings out of {total} are translated", "deactivate": "Disable translation buttons", "help": "Click the 'translate'-icon next to a string to enter or update a piece of text. You need a Weblate-account for this. Create one with your OSM-username to automatically unlock translation mode.", diff --git a/langs/es.json b/langs/es.json index f5316e305..f2b9ed4cc 100644 --- a/langs/es.json +++ b/langs/es.json @@ -11,9 +11,23 @@ "delete": "Eliminar", "explanations": { "hardDelete": "Este punto será eliminado en OpenStreetMap. Puede ser recuperado por un colaborador experimentado", - "selectReason": "Por favor, seleccione el motivo por el que esta característica debe ser eliminada" + "selectReason": "Por favor, seleccione el motivo por el que esta característica debe ser eliminada", + "softDelete": "Esta característica se actualizará y ocultará en esta aplicación. <spann class='subtle'>{reason}" }, "isDeleted": "Esta función se ha eliminado", + "isntAPoint": "Solo los puntos pueden ser eliminados, esta característica es una vía, área o relación.", + "loading": "Inspeccionando las propiedades para comprobar si esta característica puede ser eliminada.", + "loginToDelete": "Debes de haber iniciado sesión para eliminar un punto", + "notEnoughExperience": "Este punto fue hecho por otra persona.", + "onlyEditedByLoggedInUser": "Este punto solo ha sido editado por ti, puedes eliminarlo de manera segura.", + "partOfOthers": "Este punto forma parte de alguna vía o relación y no puede ser eliminada de manera directa.", + "readMessages": "Tienes mensajes sin leer. Léelos antes de eliminar un punto - alguien puede tener algún comentario", + "reasons": { + "disused": "Esta característica está fuera de uso o eliminada", + "duplicate": "Este punto es un duplicado de otra característica", + "notFound": "Esta característica no se puedo encontrar", + "test": "Esto era un punto de pruebas - la característica en realidad nunca estuvo ahí" + }, "safeDelete": "Este punto puede ser eliminado con seguridad.", "useSomethingElse": "Utilice otro editor de OpenStreetMap para eliminarlo", "whyDelete": "¿Por qué debería eliminarse este punto?" @@ -25,6 +39,7 @@ }, "general": { "about": "Edita fácilmente y añade puntos en OpenStreetMap de un tema concreto", + "aboutMapcomplete": "

    Aceca de MapComplete

    Lo utilizamos para añadir información de OpenStreetMap en un único tema. Responde preguntas, y en minutos tus contribuciones estarán disponibles en todos lados. El mantenedor del tema define elementos, preguntas e idiomas para él.

    Descubre más

    MapComplete siempre ofrece el siguiente paso para aprender más sobre OpenStreetMap.

    • Cuando se embebe en un sitio web, el iframe enlaza a un MapComplete a pantalla completa
    • La versión a pantalla completa ofrece información sobre OpenStreetMpa
    • Se puede ver el trabajo sin iniciar sesión, pero la edición requiere una cuenta de OSM.
    • Si no has iniciado sesión, se te pedirá que lo hagas
    • Una vez que hayas respondido a una simple pregunta, podrás añadir nuevos puntos al mapa
    • Después de un poco, las etiquetas de OSM se mostrarán, después de enlazar a la wiki


    ¿Te fijaste en un problema? Tienes una petición de característica?¿Quieres ayudar a traducir? Ve al código fuente o issue tracker.

    ¿Quieres ver tu progreso? Sigue a la cuenta de ediciones en OsmCha.

    ", "add": { "addNew": "Añadir {category}", "addNewMapLabel": "Haga clic aquí para añadir un nuevo ítem", @@ -35,6 +50,7 @@ "hasBeenImported": "Este punto ya ha sido importado", "import": { "hasBeenImported": "Este objeto ya ha sido importado", + "howToTest": "Para probar, añade test=true o backend=osm-test a la URL. El conjunto de cambios se imprimirá en la consola. Por favor abre un PR para oficializar este tema o activar el botón \"importar\".", "importTags": "El elemento recibirá {tags}", "officialThemesOnly": "El botón de importación está desactivado para los temas no oficiales para evitar accidentes", "wrongType": "Este elemento no es un punto o una vía y no puede ser importado", @@ -60,38 +76,74 @@ "attribution": { "attributionContent": "

    Todos los datos son proporcionados por OpenStreetMap, reutilizables libremente bajo la Licencia Abierta de Bases de Datos (ODL).

    ", "attributionTitle": "Aviso de atribución", + "codeContributionsBy": "MapComplete ha sido construido por {contributors} y {hiddenCount} más contribuidores", + "donate": "Apoya a MapComplete de manera financiera", + "editId": "Abre el editor en línea de OpenStreetMap aquí", + "editJosm": "Edita aquí conJOSM", "iconAttribution": { "title": "Iconos usados" }, + "josmNotOpened": "No se pudo llegar a JSOM. Asegúrate de que esta abierto y que el control remoto esta activado", + "josmOpened": "JOSM está abierto", "mapContributionsBy": "La información visible actual tiene ediciones hechas por {contributors}", - "themeBy": "Tema mantenido por {author}" + "mapContributionsByAndHidden": "Los datos actualmente visibles tienen ediciones hechas por {contributors} y {hiddenCount} más contribuidores", + "openIssueTracker": "Reportar un error", + "openMapillary": "Abrir Mapillary aquí", + "openOsmcha": "Ver las últimas ediciones hechas con {theme}", + "themeBy": "Tema mantenido por {author}", + "translatedBy": "MapComplete ha sido traducido por {contributors} y {hiddenCount} más contribuidores" }, "back": "Atrás", + "backToMapcomplete": "Volver a la vista de temas", "backgroundMap": "Mapa de fondo", "cancel": "Cancelar", "confirm": "Confirmar", "customThemeIntro": "

    Temas personalizados

    Estos son los temas generados por los usuarios que han sido visitados previamente.", "download": { - "exporting": "Exportando…" + "downloadAsPdf": "Descargar un PDF del mapa actual", + "downloadAsPdfHelper": "Ideal para imprimir el mapa actual", + "downloadAsSvg": "Descargar un SVG del mapa actual", + "downloadCSV": "Descargar los datos visibles como CSV", + "downloadCSVHelper": "Compatible con LibreOffice Calc, Excel, …", + "downloadFeatureAsGeojson": "Descargar como un archivo GeoJson", + "downloadFeatureAsGpx": "Descargar como archivo GPX", + "downloadGeoJsonHelper": "Compatible con QGIS, ArcGIS, ESRI, …", + "downloadGeojson": "Descargar los datos visibles como GeoJSON", + "downloadGpx": "Descargar como archivo GPX", + "downloadGpxHelper": "Un archivo GPX puede ser utilizado con la mayor parte de dispositivos y aplicaciones de navegación", + "exporting": "Exportando…", + "includeMetaData": "Incluir metadatos (último editor, valores calculados, ...)", + "licenseInfo": "

    Aviso de derechos

    Los datos provistos están disponibles bajo ODbL. Reutilizarlos es gratis para cualquier propósito, pero
    • la actribución © contribuidores d e OpenStreetMap se requiere
    • Cualquier cambio debe de utilizar la licencia
    Por favor leer todo el aviso de derechos para detalles.", + "noDataLoaded": "Aún no se han cargado ningunos daos. La descarga estará disponible proximamente", + "title": "Descargar los datos visibles", + "uploadGpx": "Sube tu traza a OpenStreetMap" }, + "error": "Algo fue mal", "example": "Ejemplo", "examples": "Ejemplos", "fewChangesBefore": "Contesta unas cuantas preguntas sobre puntos existentes antes de añadir nuevos.", "getStartedLogin": "Entra en OpenStreetMap para empezar", "getStartedNewAccount": " o crea una nueva cuenta", "goToInbox": "Abrir mensajes", + "histogram": { + "error_loading": "No se pudo cargar el histograma" + }, "layerSelection": { "title": "Seleccionar capas", "zoomInToSeeThisLayer": "Amplía para ver esta capa" }, "loading": "Cargando…", "loadingTheme": "Cargar {theme}...", + "loginFailed": "El inicio de sesión en OpenStreetMap falló", + "loginOnlyNeededToEdit": "Si quieres editar el mapa", "loginToStart": "Entra para contestar esta pregunta", "loginWithOpenStreetMap": "Acceder con OpenStreetMap", "logout": "Cerrar la sesión", "morescreen": { "createYourOwnTheme": "Crea tu propia petición completa de MapComplete desde cero.", + "hiddenExplanation": "Estos temas solo son visibles para aquellos con el enlace. Has descubierto {hidden_discovered} de {total_hidden} temas ocultos.", "intro": "

    Más peticiones

    Te gusta captar datos?
    Hay más capas disponibles.", + "previouslyHiddenTitle": "Temas ocultos previamente visitados", "requestATheme": "Si quieres que te hagamos una petición propia , pídela aquí.", "streetcomplete": "Otra aplicación similar es StreetComplete." }, @@ -99,6 +151,7 @@ "next": "Siguiente", "noNameCategory": "{category} sin nombre", "noTagsSelected": "No se han seleccionado etiquetas", + "notValid": "Selecciona un valor válido para continuar", "number": "número", "oneSkippedQuestion": "Has ignorado una pregunta", "openStreetMapIntro": "

    Un mapa abierto

    ¿No sería genial si hubiera un solo mapa, que todos pudieran usar y editar libremente?¿Un solo lugar para almacenar toda la información geográfica? Entonces, todos esos sitios web con mapas diferentes, pequeños e incompatibles (que siempre están desactualizados) ya no serían necesarios.

    OpenStreetMap es ese mapa. Los datos del mapa se pueden utilizar de forma gratuita (con atribución y publicación de cambios en esos datos). Además de eso, todos pueden agregar libremente nuevos datos y corregir errores. Este sitio web también usa OpenStreetMap. Todos los datos provienen de allí, y tus respuestas y correcciones también se añadirán allí.

    Muchas personas y aplicaciones ya usan OpenStreetMap: Maps.me, OsmAnd, pero también los mapas de Facebook, Instagram, Apple y Bing son (en parte) impulsados ​​por OpenStreetMap. Si cambias algo aquí, también se reflejará en esas aplicaciones, en su próxima actualización

    ", @@ -122,7 +175,8 @@ "pdf": { "attr": "Datos cartográficos © colaboradores de OpenStreetMap, reutilizables en virtud de la ODbL", "attrBackground": "Capa de fondo: {background}", - "generatedWith": "Generado como MapComplete.osm.be" + "generatedWith": "Generado como MapComplete.osm.be", + "versionInfo": "v{version} - generado el {date}" }, "pickLanguage": "Escoge idioma: ", "questions": { @@ -134,8 +188,10 @@ "websiteOf": "Cual es la página web de {category}?" }, "readYourMessages": "Lee todos tus mensajes de OpenStreetMap antes de añadir nuevos puntos.", + "removeLocationHistory": "Eliminar el historial de ubicaciones", "returnToTheMap": "Volver al mapa", "save": "Guardar", + "screenToSmall": "Abrir {theme} en una ventana nueva", "search": { "error": "Alguna cosa no ha ido bien...", "nothing": "Nada encontrado.", @@ -183,24 +239,32 @@ }, "welcomeBack": "Has entrado, bienvenido.", "wikipedia": { + "doSearch": "Busca arriba para ver los resultados", + "failed": "La carga de la entrada de Wikipedia falló", "loading": "Cargando Wikipedia...", + "noResults": "No se encontró nada para {search}", + "noWikipediaPage": "Este ítem de wikidata aún no tiene una página de Wikipedia correspondiente.", "previewbox": { "born": "Nacido: {value}", "died": "Murió: {value}" }, + "searchWikidata": "Buscar en Wikidata", "wikipediaboxTitle": "Wikipedia" } }, "image": { "addPicture": "Añadir foto", "ccb": "bajo licencia CC-BY", + "ccbExplanation": "La licencia CC-BY implica cualquiera podría utilizar tu fotografía para cualquier propósito, pero tienen que atribuirte", "ccbs": "bajo licencia CC-BY-SA", "cco": "en dominio público", + "ccoExplanation": "Añadir una fotografía en el dominio público implica que cualquiera puede hacer cualquier cosa con tu fotografía", "doDelete": "Borrar imagen", "dontDelete": "Cancelar", "isDeleted": "Borrada", "pleaseLogin": "Acceda para cargar una imagen", "respectPrivacy": "No fotografíe personas ni matrículas. No cargue datos de Google Maps, Google StreetView u otras fuentes protegidas por derechos de autor.", + "toBig": "Tu imagen es demasiado grande, ya que pesa {actual_size}. Por favor utiliza imágenes de como máximo {max_size}", "uploadDone": "Se ha añadido la imagen. Gracias por ayudar.", "uploadFailed": "No se pudo cargar la imagen. ¿Tiene Internet y se permiten las API de terceros? El navegador Brave o uMatrix podría bloquearlas.", "uploadMultipleDone": "Se han añadido {count} imágenes. Gracias por ayudar.", @@ -209,14 +273,35 @@ "willBePublished": "La imagen se publicará " }, "importHelper": { + "askMetadata": { + "downloadGeojson": "Descargar geojson", + "giveDescription": "Por favor, escribe una pequeña descripción para alguien que vea la nota. Una buena nota describe lo que el contribuidor tiene que hacer, ej; Puede que haya un banco aquí. Si estás por aquí, ¿Podrías por favor comprueba e indica si el banco existe o no? (Un enlace a MapComplete se añadirá automáticamente)", + "giveWikilink": "¿En qué wikipágina puede encontrar uno más información sobre esta importación?", + "intro": "Antes de añadir {count} notas, por favor provee alguna información extra.", + "orDownload": "Alternativamente, puedes descargar el conjunto de datos para importar directamente", + "shouldBeOsmWikilink": "Se espera un enlace a una página en wiki.openstreetmap.org", + "shouldBeUrl": "No una URL válida", + "shouldNotBeHomepage": "No, tampoco se permite la página de inicio. Introduce la URL de una wikipágina de verdad para documentar tu importación", + "title": "Especificar metadatos" + }, + "compareToAlreadyExistingNotes": { + "completelyImported": "Todos los puntos propuestos ya tienen (o tenían) una nota de importación", + "loading": "Cargando las notas desde OSM", + "loadingFailed": "La carga de las notas falló debido a {error}", + "mapExplanation": "Los elementos rojos en el siguiente mapa son todos los puntos de datos de tu conjunto de datos. Hay {length} elementos en tu conjunto de datos.", + "noPreviousNotesFound": "No se han encontrado notas de importación previas", + "nothingNearby": "Todos los puntos propuestos no tienen una nota de importación previa cerca", + "someNearby": "{hasNearby} puntos sí que tienen una nota de importación ya existente a menos de {distance} metros", + "title": "Comparar con notas existentes", + "wontBeImported": "Estos puntos de datos no serán importados y se muestran como puntos en el mapa de debajo" + }, "mapPreview": { "title": "Previsualización de mapa" }, "selectFile": { "title": "Seleccionar archivo" }, - "title": "Ayudante de importación", - "validateDataTitle": "Validar datos" + "title": "Ayudante de importación" }, "importLayer": { "layerName": "Posible {title}", @@ -235,7 +320,7 @@ }, "notes": { "addComment": "Añadir comentario", - "anonymous": "Usuario anónimo", + "anonymous": "Usuarioi anónimo", "closeNote": "Cerrar nota", "reopenNote": "Reabrir nota" }, diff --git a/langs/fil.json b/langs/fil.json index 2f6a749d0..38317d987 100644 --- a/langs/fil.json +++ b/langs/fil.json @@ -7,14 +7,48 @@ }, "delete": { "cancel": "Kanselá", - "isDeleted": "Tinanggal na ang tampók na ito", - "isntAPoint": "Mga buko (point) lang ang maaring tanggalin, ang piniling tampók ay isang way, area o relation.", - "loginToDelete": "Dapat kang naka-logged in para matanggal ang buko(point)", - "explanations": { - "selectReason": "Pumili ng dahilan kung bakit dapat tanggalin ang tampók na ito." - }, "cannotBeDeleted": "Ang tampok na ito ay hindi matatanggal", + "delete": "Tanggalin", + "explanations": { + "hardDelete": "Ang tampók na ito ay tatanggalin sa OpenStreetMap. Maari itong ibalik ng mga bihasang tiga-ambag", + "selectReason": "Pumili ng dahilan kung bakit dapat tanggalin ang tampók na ito.", + "softDelete": "Ang tampók na ito ay babaguhin at itatago sa application. {reason}" + }, + "isDeleted": "Tinanggal na ang tampók na ito", + "isntAPoint": "Mga bukó (point) lang ang maaring tanggalin, ang piniling tampók ay isang way, area o relation.", "loading": "Sinisiyasat ang mga katangian ng tampók para alamin kung maari itong tanggalin.", - "delete": "Tanggalin" + "loginToDelete": "Dapat kang naka-logged in para matanggal ang bukó(point)", + "notEnoughExperience": "Ang tampók na ito ay ginawa ng ibang tao.", + "onlyEditedByLoggedInUser": "Ikaw ang patnugot ng tampók na ito, at maari mo itong tanggalin.", + "partOfOthers": "Ang bukó (point) na ito ay bahagi ng ibang way o relation, at hindi maaring tanggalin.", + "readMessages": "Meron kang mga bagong mensahe. Basahin ang mga ito bago tanggalin ang tampók - maaring may puná para sa'yo", + "reasons": { + "disused": "Ang tampók na ito ay di-aktibo o tinanggal na", + "duplicate": "Ang bukó na 'to ay kahalintulad ng iba pang tampók", + "notFound": "Ang tampók na 'to ay 'di masumpongan", + "test": "Ang bukóng ito ay ginamit na pang-subok - ang tampók ay 'di talaga inimpok" + }, + "safeDelete": "Ang tampók na ito ay di-makapipinsalang tanggalin.", + "useSomethingElse": "Sa halip, gumamit ng iba pang editor ng OpenStreetMap para tanggalin", + "whyDelete": "Bakit dapat tanggalin ang tampók na 'to?" + }, + "favourite": { + "loginNeeded": "

    Mag log-in

    Ang personal na pagkakaayos ay para lang sa mga gumagamit ng OpenStreetMap", + "reload": "Muling pasanin ang datos" + }, + "general": { + "about": "Madaling i-edit at mag-dagdag sa OpenStreetMap gamit ang mga partikular na tikha", + "add": { + "addNew": "Dagdagan ng {category}", + "addNewMapLabel": "I-click ito para mag-dagdag ng bagong bagay", + "confirmButton": "Magdagdag ng {category}
    Makikita ng lahat ang idinagdag mo
    ", + "confirmIntro": "

    Mag-dagdag ng {title}?

    Ang tampók na ida-dagdag mo ay makikita ng lahat. Paki-usap, mag-dagdag lamang ng mga bagay na tutuong umiiral. Marami pang mga aplikasyon ang gumagamit ng datos na ito.", + "disableFilters": "Huwag paganahin ang lahat ng filter", + "disableFiltersExplanation": "May mga tampók na maaring nai-tago ng filter", + "hasBeenImported": "Ang bukóng ito ay nai-angkat na", + "import": { + "hasBeenImported": "Ang object na ito ay nai-angkat na" + } + } } } diff --git a/langs/gl.json b/langs/gl.json index ce0e6ed5e..42dc16620 100644 --- a/langs/gl.json +++ b/langs/gl.json @@ -42,11 +42,6 @@ "getStartedLogin": "Entra no OpenStreetMap para comezar", "getStartedNewAccount": " ou crea unha nova conta", "goToInbox": "Abrir mensaxes", - "index": { - "intro": "O MapComplete é un visor e editor do OpenStreetMap, que te amosa información sobre un tema específico.", - "pickTheme": "Escolle un tema para comezar.", - "title": "Benvido ao MapComplete" - }, "layerSelection": { "title": "Seleccionar capas", "zoomInToSeeThisLayer": "Achégate para ver esta capa" diff --git a/langs/hu.json b/langs/hu.json index a5750aa36..915c5e98d 100644 --- a/langs/hu.json +++ b/langs/hu.json @@ -267,8 +267,12 @@ "willBePublished": "A képed így lesz közzétéve: " }, "importHelper": { - "allAttributesSame": "Ez a címke minden importálandó objektumon szerepel", - "description": "Az importálási segédprogram egy külső adatkészletet konvertál OSM-jegyzetekké. A külső adatkészletnek meg kell felelnie a MapComplete egyik meglévő rétegének. Az importálóba helyezett minden egyes elemhez egyetlen jegyzet fog létrejönni. Ezek a jegyzetek a megfelelő objektumokkal együtt fognak megjelenni ezeken a térképekben, hogy könnyen fel lehessen rajzolni őket a térképre." + "introduction": { + "description": "Az importálási segédprogram egy külső adatkészletet konvertál OSM-jegyzetekké. A külső adatkészletnek meg kell felelnie a MapComplete egyik meglévő rétegének. Az importálóba helyezett minden egyes elemhez egyetlen jegyzet fog létrejönni. Ezek a jegyzetek a megfelelő objektumokkal együtt fognak megjelenni ezeken a térképekben, hogy könnyen fel lehessen rajzolni őket a térképre." + }, + "previewAttributes": { + "allAttributesSame": "Ez a címke minden importálandó objektumon szerepel" + } }, "index": { "#": "Ezek a szövegek akkor jelennek meg a témagombok felett, ha nincs betöltve téma", diff --git a/langs/layers/ca.json b/langs/layers/ca.json index 7c63cac57..15daa3a58 100644 --- a/langs/layers/ca.json +++ b/langs/layers/ca.json @@ -1,4 +1,542 @@ { + "address": { + "description": "Adreces" + }, + "artwork": { + "name": "Obres d'art", + "tagRenderings": { + "artwork-artwork_type": { + "mappings": { + "0": { + "then": "Arquitectura" + }, + "1": { + "then": "Mural" + }, + "2": { + "then": "Pintura" + }, + "3": { + "then": "Escultura" + }, + "4": { + "then": "Estàtua" + }, + "5": { + "then": "Bust" + }, + "6": { + "then": "Pedra" + }, + "7": { + "then": "Instal·lació" + }, + "8": { + "then": "Grafiti" + }, + "9": { + "then": "Relleu" + }, + "11": { + "then": "Enrajolat" + } + } + } + }, + "title": { + "render": "Obra d'art" + } + }, + "barrier": { + "name": "Barreres", + "presets": { + "0": { + "title": "una pilona" + } + }, + "tagRenderings": { + "Bollard type": { + "mappings": { + "0": { + "then": "Pilona desmuntable" + }, + "1": { + "then": "Pilona fixa" + }, + "4": { + "then": "Pilona retràctil" + } + } + } + }, + "title": { + "mappings": { + "0": { + "then": "Pilona" + }, + "1": { + "then": "Barrera ciclista" + } + }, + "render": "Barrera" + } + }, + "bench": { + "name": "Bancs", + "presets": { + "0": { + "title": "un banc" + } + }, + "tagRenderings": { + "bench-backrest": { + "mappings": { + "0": { + "then": "Respatller: sí" + }, + "1": { + "then": "Respatller: No" + } + } + }, + "bench-colour": { + "mappings": { + "0": { + "then": "Color: marró" + }, + "1": { + "then": "Color: verd" + }, + "2": { + "then": "Color: gris" + }, + "3": { + "then": "Color: blanc" + }, + "4": { + "then": "Color: vermell" + }, + "5": { + "then": "Color: negre" + }, + "6": { + "then": "Color: blau" + }, + "7": { + "then": "Color: groc" + } + }, + "render": "Color: {colour}" + }, + "bench-material": { + "mappings": { + "0": { + "then": "Material: fusta" + }, + "1": { + "then": "Material: metall" + }, + "2": { + "then": "Material: pedra" + }, + "3": { + "then": "Material: ciment" + }, + "4": { + "then": "Material: plàstic" + }, + "5": { + "then": "Material: acer" + } + }, + "render": "Material: {material}" + }, + "bench-seats": { + "render": "{seats} seients" + } + }, + "title": { + "render": "Banc" + } + }, + "bench_at_pt": { + "tagRenderings": { + "bench_at_pt-name": { + "render": "{name}" + } + }, + "title": { + "render": "Banc" + } + }, + "bicycle_library": { + "name": "Biblioteca per a bicicletes", + "title": { + "render": "Biblioteca per a bicicletes" + } + }, + "bicycle_rental": { + "tagRenderings": { + "9": { + "rewrite": { + "into": { + "4": { + "1": "bicicleta de muntanya" + }, + "6": { + "1": "tàndem" + } + } + } + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + } + } + }, + "bike_cafe": { + "name": "Cafeteria per a bicicletes", + "title": { + "render": "Cafeteria per a bicicletes" + } + }, + "bike_parking": { + "name": "Aparcament per a bicicletes", + "tagRenderings": { + "Access": { + "mappings": { + "0": { + "then": "Accessible al públic" + } + }, + "render": "{access}" + }, + "Bicycle parking type": { + "mappings": { + "0": { + "then": "Bastidors de grapes" + }, + "1": { + "then": "Portarodes/bucles" + }, + "2": { + "then": "Suport de manillar" + }, + "3": { + "then": "Enganxament" + }, + "4": { + "then": "De dos nivells" + }, + "6": { + "then": "Pilona" + } + } + }, + "Underground?": { + "mappings": { + "0": { + "then": "Aparcament subterrani" + }, + "2": { + "then": "Aparcament al terrat" + } + } + } + }, + "title": { + "render": "Aparcament per a bicicletes" + } + }, + "bike_repair_station": { + "tagRenderings": { + "bike_repair_station-electrical_pump": { + "mappings": { + "0": { + "then": "Bomba manual" + }, + "1": { + "then": "Bomba elèctrica" + } + } + }, + "bike_repair_station-opening_hours": { + "mappings": { + "0": { + "then": "Sempre obert" + } + } + } + }, + "title": { + "mappings": { + "2": { + "then": "Bomba trencada" + }, + "4": { + "then": "Bomba de bicicleta" + } + } + } + }, + "bike_shop": { + "name": "Botiga/reparació de bicicletes", + "title": { + "render": "Botiga/reparació de bicicletes" + } + }, + "bike_themed_object": { + "title": { + "mappings": { + "1": { + "then": "Pista ciclable" + } + } + } + }, + "binocular": { + "description": "Prismàtics", + "name": "Prismàtics", + "presets": { + "0": { + "title": "uns prismàtics" + } + }, + "title": { + "render": "Prismàtics" + } + }, + "birdhide": { + "filter": { + "0": { + "options": { + "0": { + "question": "Accessible per a cadires de rodes" + } + } + } + } + }, + "cafe_pub": { + "filter": { + "0": { + "options": { + "0": { + "question": "Obert ara" + } + } + } + }, + "presets": { + "0": { + "title": "un bar" + }, + "1": { + "title": "un pub" + }, + "2": { + "title": "un cafè" + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "Bar" + } + }, + "charging_station": { + "filter": { + "2": { + "options": { + "0": { + "question": "Tots els connectors" + } + } + } + }, + "name": "Estacions de càrrega", + "tagRenderings": { + "Available_charging_stations (generated)": { + "mappings": { + "4": { + "then": "Chademo" + }, + "5": { + "then": "Chademo" + } + } + } + }, + "title": { + "render": "Estació de càrrega" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " minuts", + "humanSingular": " minut" + }, + "1": { + "human": " hores", + "humanSingular": " hora" + }, + "2": { + "human": " dies", + "humanSingular": " dia" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": "Volts" + } + } + }, + "2": { + "applicableUnits": { + "0": { + "human": "A" + } + } + }, + "3": { + "applicableUnits": { + "0": { + "human": "quilovats" + }, + "1": { + "human": "megavats" + } + } + } + } + }, + "climbing": { + "tagRenderings": { + "name": { + "render": "{name}" + } + }, + "title": { + "mappings": { + "2": { + "then": "Llocs d'escalada" + } + } + } + }, + "climbing_club": { + "tagRenderings": { + "climbing_club-name": { + "render": "{name}" + } + } + }, + "climbing_gym": { + "tagRenderings": { + "name": { + "render": "{name}" + } + } + }, + "climbing_opportunity": { + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + } + } + }, + "climbing_route": { + "tagRenderings": { + "Name": { + "render": "{name}" + } + } + }, + "crossings": { + "name": "Encreuaments", + "presets": { + "0": { + "title": "un pas de vianants" + } + }, + "tagRenderings": { + "crossing-type": { + "mappings": { + "2": { + "then": "Pas de zebra" + } + } + } + }, + "title": { + "mappings": { + "0": { + "then": "Semàfor" + } + }, + "render": "Encreuament" + } + }, + "cycleways_and_roads": { + "tagRenderings": { + "cycleway-lane-track-traffic-signs": { + "mappings": { + "0": { + "then": "Via ciclista obligatòria" + }, + "2": { + "then": "Via segregada a peu/ciclista" + }, + "3": { + "then": "Via no segregada a peu/ciclista" + } + } + }, + "cycleway-traffic-signs": { + "mappings": { + "0": { + "then": "Via ciclista obligatòria" + }, + "2": { + "then": "Via segregada a peu/ciclista" + }, + "3": { + "then": "Via no segregada a peu/ciclista" + }, + "4": { + "then": "Via ciclista obligatòria" + } + } + } + }, + "title": { + "mappings": { + "0": { + "then": "Via ciclista" + }, + "1": { + "then": "Carril compartit" + }, + "2": { + "then": "Carril bici" + }, + "4": { + "then": "Carrer ciclista" + } + }, + "render": "Vies ciclistes" + } + }, "defibrillator": { "name": "Desfibril·ladors", "presets": { @@ -48,17 +586,125 @@ "defibrillator-level": { "question": "A quina planta està el desfibril·lador localitzat?", "render": "Aquest desfibril·lador és a la planta {level}" + }, + "defibrillator-opening_hours": { + "render": "{opening_hours_table(opening_hours)}" + }, + "defibrillator-survey:date": { + "mappings": { + "0": { + "then": "Comprovat avui!" + } + } } }, "title": { "render": "Desfibril·lador" } }, + "direction": { + "name": "Direcció de la visualització" + }, + "drinking_water": { + "name": "Aigua potable", + "title": { + "render": "Aigua potable" + } + }, + "entrance": { + "name": "Entrada", + "title": { + "render": "Entrada" + } + }, + "extinguisher": { + "title": { + "render": "Extintors" + } + }, + "food": { + "filter": { + "0": { + "options": { + "0": { + "question": "Obert ara" + } + } + } + }, + "presets": { + "0": { + "title": "un restaurant" + }, + "1": { + "title": "un de menjar ràpid" + } + }, + "title": { + "mappings": { + "0": { + "then": "Restaurant {name}" + }, + "1": { + "then": "Lloc de menjar ràpid {name}" + }, + "2": { + "then": "Menjar ràpid" + } + }, + "render": "Restaurant" + } + }, "ghost_bike": { + "name": "Bicicleta blanca", "tagRenderings": { "ghost_bike-inscription": { "render": "{inscription}" } + }, + "title": { + "render": "Bicicleta blanca" + } + }, + "hackerspace": { + "tagRenderings": { + "hackerspaces-opening_hours": { + "mappings": { + "0": { + "then": "Obert 24/7" + } + }, + "render": "{opening_hours_table()}" + } + }, + "title": { + "mappings": { + "0": { + "then": " {name}" + } + } + } + }, + "hydrant": { + "title": { + "render": "Hidrant" + } + }, + "information_board": { + "name": "Panells d'informació", + "title": { + "render": "Panell d'informació" + } + }, + "map": { + "name": "Mapes", + "presets": { + "0": { + "title": "un mapa" + } + }, + "title": { + "render": "Mapa" } }, "nature_reserve": { @@ -68,24 +714,249 @@ } } }, + "note": { + "title": { + "render": "Nota" + } + }, + "observation_tower": { + "name": "Torres d'observació", + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "Torre d'observació" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " metre" + } + } + } + } + }, + "parking": { + "name": "Aparcament" + }, + "picnic_table": { + "name": "Taules de pícnic", + "title": { + "render": "Taula de pícnic" + } + }, "playground": { + "description": "Parcs infantils", + "name": "Parcs infantils", + "presets": { + "0": { + "title": "un parc infantil" + } + }, "tagRenderings": { "playground-email": { "render": "{email}" }, + "playground-opening_hours": { + "mappings": { + "1": { + "then": "Sempre accessible--" + } + } + }, "playground-phone": { "render": "{phone}" } + }, + "title": { + "mappings": { + "0": { + "then": "Parc infantil {name}" + } + }, + "render": "Parc infantil" + } + }, + "public_bookcase": { + "name": "Bústies per llibres", + "presets": { + "0": { + "title": "una bústia per a llibres" + } + }, + "title": { + "render": "Bústia per llibres" + } + }, + "recycling": { + "name": "Residus", + "tagRenderings": { + "opening_hours": { + "mappings": { + "0": { + "then": "24/7" + } + } + } } }, "shops": { + "name": "Botiga", "tagRenderings": { + "shops-opening_hours": { + "render": "{opening_hours_table(opening_hours)}" + }, "shops-phone": { "render": "{phone}" }, + "shops-shop": { + "mappings": { + "1": { + "then": "Supermercat" + }, + "3": { + "then": "Perruqueria" + }, + "4": { + "then": "Fleca" + } + } + }, "shops-website": { "render": "{website}" } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + }, + "1": { + "then": "{shop}" + } + }, + "render": "Botiga" + } + }, + "sport_pitch": { + "name": "Camps d'esports", + "title": { + "render": "Camp d'esports" + } + }, + "surveillance_camera": { + "name": "Càmeres de videovigilància", + "title": { + "render": "Càmera de videovigilància" + } + }, + "toilet": { + "name": "Lavabos", + "title": { + "render": "Lavabo" + } + }, + "trail": { + "name": "Camins", + "title": { + "render": "Camí" + } + }, + "tree_node": { + "name": "Arbre", + "presets": { + "2": { + "title": "un arbre" + } + }, + "tagRenderings": { + "tree-decidouous": { + "mappings": { + "1": { + "then": "Perenne." + } + } + }, + "tree-leaf_type": { + "mappings": { + "0": { + "then": "De fulla ampla" + }, + "1": { + "then": "Amb fulles d'agulla" + } + } + } + }, + "title": { + "render": "Arbre" + } + }, + "viewpoint": { + "name": "Mirador", + "presets": { + "0": { + "title": "un mirador" + } + }, + "title": { + "render": "Mirador" + } + }, + "visitor_information_centre": { + "title": { + "mappings": { + "1": { + "then": "{name}" + } + }, + "render": "{name}" + } + }, + "waste_basket": { + "name": "Paperera", + "title": { + "render": "Paperera" + } + }, + "watermill": { + "name": "Molí d'aigua" + }, + "windturbine": { + "title": { + "mappings": { + "0": { + "then": "{name}" + } + } + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " megavats" + }, + "1": { + "human": " quilovats" + }, + "2": { + "human": " vats" + }, + "3": { + "human": " gigavats" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " metre" + } + } + } } } } \ No newline at end of file diff --git a/langs/layers/da.json b/langs/layers/da.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/langs/layers/da.json @@ -0,0 +1 @@ +{} diff --git a/langs/layers/de.json b/langs/layers/de.json index a1f52cdcd..0220e9146 100644 --- a/langs/layers/de.json +++ b/langs/layers/de.json @@ -213,6 +213,16 @@ "question": "Wie breit ist die kleinste Öffnung neben den Barrieren?", "render": "Breite der Öffnung: {width:opening} m" }, + "barrier_type": { + "mappings": { + "0": { + "then": "Dies ist ein einzelner Poller auf der Straße" + }, + "1": { + "then": "Dies ist eine Fahrradbarriere, die Radfahrer abbremst" + } + } + }, "bicycle=yes/no": { "mappings": { "0": { @@ -223,16 +233,6 @@ } }, "question": "Kann ein Radfahrer das Hindernis passieren?" - }, - "barrier_type": { - "mappings": { - "1": { - "then": "Dies ist eine Fahrradbarriere, die Radfahrer abbremst" - }, - "0": { - "then": "Dies ist ein einzelner Poller auf der Straße" - } - } } }, "title": { @@ -248,6 +248,7 @@ } }, "bench": { + "description": "Diese Karte stellt Sitzbänke aus Holz, Metall, Stein, ... dar und stellt ein paar Fragen, um weitere Informationen zu ergänzen.", "name": "Sitzbänke", "presets": { "0": { @@ -335,10 +336,10 @@ }, "title": { "render": "Sitzbank" - }, - "description": "Diese Karte stellt Sitzbänke aus Holz, Metall, Stein, ... dar und stellt ein paar Fragen, um weitere Informationen zu ergänzen." + } }, "bench_at_pt": { + "description": "Eine Ebene mit allen Haltestellen des öffentlichen Nahverkehrs, die über eine Sitzbank verfügen", "name": "Sitzbänke an Haltestellen", "tagRenderings": { "bench_at_pt-bench_type": { @@ -369,8 +370,7 @@ } }, "render": "Sitzbank" - }, - "description": "Eine Ebene mit allen Haltestellen des öffentlichen Nahverkehrs, die über eine Sitzbank verfügen" + } }, "bicycle_library": { "description": "Eine Einrichtung, in der Fahrräder für längere Zeit geliehen werden können", @@ -418,56 +418,30 @@ } }, "bicycle_rental": { - "name": "Fahrradverleih", + "deletion": { + "extraDeleteReasons": { + "0": { + "explanation": "{title()} ist dauerhaft geschlossen" + } + }, + "nonDeleteMappings": { + "0": { + "then": "Dieser Fahrradladen vermietete früher Fahrräder, aber jetzt nicht mehr" + } + } + }, "description": "Fahrradverleihstationen", + "name": "Fahrradverleih", + "presets": { + "0": { + "description": "Ein Geschäft, das sich auf den Fahrradverleih konzentriert", + "title": "Ein Fahrradverleih" + }, + "1": { + "title": "Ein Fahrradverleih" + } + }, "tagRenderings": { - "bicycle_rental_type": { - "mappings": { - "1": { - "then": "Dies ist ein Vermietungsunternehmen, das verschiedene Gegenstände und/oder Fahrzeuge vermietet. Es vermietet auch Fahrräder, aber das ist nicht der Hauptschwerpunkt" - }, - "3": { - "then": "Dies ist eine automatisierte Dockingstation, bei der ein Fahrrad mechanisch in einer Struktur verriegelt wird" - }, - "0": { - "then": "Dies ist ein Geschäft, dessen Schwerpunkt auf dem Fahrradverleih liegt" - }, - "2": { - "then": "Dies ist ein Geschäft, das Fahrräder verkauft oder repariert, aber auch Fahrräder vermietet" - }, - "4": { - "then": "Es gibt einen Automaten, der Schlüssel ausgibt und annimmt, eventuell nach Authentifizierung und/oder Bezahlung. Die Fahrräder sind in der Nähe geparkt" - } - }, - "question": "Was ist das für ein Fahrradverleih?" - }, - "bicycle-types": { - "mappings": { - "6": { - "then": "Rennräder können hier gemietet werden" - }, - "2": { - "then": "BMX-Räder können hier gemietet werden" - }, - "0": { - "then": "Normale Stadtfahrräder können hier gemietet werden" - }, - "1": { - "then": "Elektrofahrräder können hier gemietet werden" - }, - "4": { - "then": "Kinderfahrräder können hier gemietet werden" - }, - "3": { - "then": "Mountainbikes können hier gemietet werden" - }, - "5": { - "then": "Tandems können hier gemietet werden" - } - }, - "question": "Welche Art von Fahrrädern und Zubehör wird hier vermietet?", - "render": "{rental} wird hier vermietet" - }, "9": { "rewrite": { "into": { @@ -494,15 +468,53 @@ } } } - } - }, - "presets": { - "0": { - "title": "Ein Fahrradverleih", - "description": "Ein Geschäft, das sich auf den Fahrradverleih konzentriert" }, - "1": { - "title": "Ein Fahrradverleih" + "bicycle-types": { + "mappings": { + "0": { + "then": "Normale Stadtfahrräder können hier gemietet werden" + }, + "1": { + "then": "Elektrofahrräder können hier gemietet werden" + }, + "2": { + "then": "BMX-Räder können hier gemietet werden" + }, + "3": { + "then": "Mountainbikes können hier gemietet werden" + }, + "4": { + "then": "Kinderfahrräder können hier gemietet werden" + }, + "5": { + "then": "Tandems können hier gemietet werden" + }, + "6": { + "then": "Rennräder können hier gemietet werden" + } + }, + "question": "Welche Art von Fahrrädern und Zubehör wird hier vermietet?", + "render": "{rental} wird hier vermietet" + }, + "bicycle_rental_type": { + "mappings": { + "0": { + "then": "Dies ist ein Geschäft, dessen Schwerpunkt auf dem Fahrradverleih liegt" + }, + "1": { + "then": "Dies ist ein Vermietungsunternehmen, das verschiedene Gegenstände und/oder Fahrzeuge vermietet. Es vermietet auch Fahrräder, aber das ist nicht der Hauptschwerpunkt" + }, + "2": { + "then": "Dies ist ein Geschäft, das Fahrräder verkauft oder repariert, aber auch Fahrräder vermietet" + }, + "3": { + "then": "Dies ist eine automatisierte Dockingstation, bei der ein Fahrrad mechanisch in einer Struktur verriegelt wird" + }, + "4": { + "then": "Es gibt einen Automaten, der Schlüssel ausgibt und annimmt, eventuell nach Authentifizierung und/oder Bezahlung. Die Fahrräder sind in der Nähe geparkt" + } + }, + "question": "Was ist das für ein Fahrradverleih?" } }, "title": { @@ -512,21 +524,10 @@ } }, "render": "Fahrradverleih" - }, - "deletion": { - "extraDeleteReasons": { - "0": { - "explanation": "{title()} ist dauerhaft geschlossen" - } - }, - "nonDeleteMappings": { - "0": { - "then": "Dieser Fahrradladen vermietete früher Fahrräder, aber jetzt nicht mehr" - } - } } }, "bicycle_tube_vending_machine": { + "description": "Eine Ebene mit Automaten für Fahrradschläuche (entweder spezielle Fahrradschlauch-Automaten oder klassische Automaten mit Fahrradschläuchen und optional zusätzlichen fahrradbezogenen Gegenständen wie Lampen, Handschuhe, Schlösser, ...)", "name": "Automaten für Fahrradschläuche", "presets": { "0": { @@ -552,10 +553,10 @@ }, "title": { "render": "Fahrradschlauch-Automat" - }, - "description": "Eine Ebene mit Automaten für Fahrradschläuche (entweder spezielle Fahrradschlauch-Automaten oder klassische Automaten mit Fahrradschläuchen und optional zusätzlichen fahrradbezogenen Gegenständen wie Lampen, Handschuhe, Schlösser, ...)" + } }, "bike_cafe": { + "description": "Ein Fahrradcafé ist ein Café, das auf Radfahrer ausgerichtet ist, zum Beispiel mit Dienstleistungen wie einer Pumpe, mit viel fahrradbezogener Dekoration, ...", "name": "Fahrrad-Cafés", "presets": { "0": { @@ -620,10 +621,10 @@ } }, "render": "Fahrrad-Café" - }, - "description": "Ein Fahrradcafé ist ein Café, das auf Radfahrer ausgerichtet ist, zum Beispiel mit Dienstleistungen wie einer Pumpe, mit viel fahrradbezogener Dekoration, ..." + } }, "bike_cleaning": { + "description": "Eine Ebene mit Einrichtungen, in denen man sein Fahrrad reinigen kann", "name": "Fahrrad-Reinigungsdienste", "presets": { "0": { @@ -669,10 +670,10 @@ } }, "render": "Fahrrad-Reinigungsdienst" - }, - "description": "Eine Ebene mit Einrichtungen, in denen man sein Fahrrad reinigen kann" + } }, "bike_parking": { + "description": "Eine Ebene, die anzeigt, wo Sie Ihr Fahrrad abstellen können", "name": "Fahrrad-Parkplätze", "presets": { "0": { @@ -778,10 +779,10 @@ }, "title": { "render": "Fahrrad-Parkplätze" - }, - "description": "Eine Ebene, die anzeigt, wo Sie Ihr Fahrrad abstellen können" + } }, "bike_repair_station": { + "description": "Eine Ebene mit Fahrradpumpen und Werkzeugständern für die Fahrradreparatur", "name": "Fahrradstationen (Reparatur, Pumpe oder beides)", "presets": { "0": { @@ -793,8 +794,8 @@ "title": "eine fahrrad-reparaturstation und pumpe" }, "2": { - "title": "eine fahrrad-reparaturstation ohne pumpe", - "description": "Werkzeug, um Ihr Fahrrad im öffentlichen Raum zu reparieren (ohne Pumpe). Die Werkzeuge sind gegen Diebstahl gesichert." + "description": "Werkzeug, um Ihr Fahrrad im öffentlichen Raum zu reparieren (ohne Pumpe). Die Werkzeuge sind gegen Diebstahl gesichert.", + "title": "eine fahrrad-reparaturstation ohne pumpe" } }, "tagRenderings": { @@ -812,6 +813,26 @@ }, "question": "Ist die Fahrradpumpe noch funktionstüchtig?" }, + "access": { + "mappings": { + "0": { + "then": "Öffentlich zugänglich" + }, + "1": { + "then": "Öffentlich zugänglich" + }, + "2": { + "then": "Nur für Kunden" + }, + "3": { + "then": "Nicht für die Allgemeinheit zugänglich" + }, + "4": { + "then": "Nicht für die Allgemeinheit zugänglich" + } + }, + "question": "Wer darf diese Reparaturstation benutzen?" + }, "bike_repair_station-available-services": { "mappings": { "0": { @@ -905,26 +926,6 @@ }, "question": "Welche Ventile werden unterstützt?", "render": "Diese Pumpe unterstützt die folgenden Ventile: {valves}" - }, - "access": { - "mappings": { - "4": { - "then": "Nicht für die Allgemeinheit zugänglich" - }, - "2": { - "then": "Nur für Kunden" - }, - "3": { - "then": "Nicht für die Allgemeinheit zugänglich" - }, - "0": { - "then": "Öffentlich zugänglich" - }, - "1": { - "then": "Öffentlich zugänglich" - } - }, - "question": "Wer darf diese Reparaturstation benutzen?" } }, "title": { @@ -946,8 +947,7 @@ } }, "render": "Fahrradstation (Pumpe & Reparatur)" - }, - "description": "Eine Ebene mit Fahrradpumpen und Werkzeugständern für die Fahrradreparatur" + } }, "bike_shop": { "description": "Ein Geschäft, das speziell Fahrräder oder verwandte Artikel verkauft", @@ -1053,16 +1053,19 @@ }, "question": "Gibt es hier Werkzeuge, um das eigene Fahrrad zu reparieren?" }, + "bike_shop-access": { + "render": "Nur zugänglich für {access}" + }, "bike_shop-email": { "question": "Wie lautet die E-Mail-Adresse von {name}?" }, "bike_shop-is-bicycle_shop": { - "render": "Dieses Geschäft ist auf den Verkauf von {shop} spezialisiert und im Bereich Fahrrad tätig", "mappings": { "0": { "then": "Dieses Geschäft konzentriert sich auf die Vermietung" } - } + }, + "render": "Dieses Geschäft ist auf den Verkauf von {shop} spezialisiert und im Bereich Fahrrad tätig" }, "bike_shop-name": { "question": "Wie heißt dieser Fahrradladen?", @@ -1073,9 +1076,6 @@ }, "bike_shop-website": { "question": "Was ist die Webseite von {name}?" - }, - "bike_shop-access": { - "render": "Nur zugänglich für {access}" } }, "title": { @@ -1100,6 +1100,7 @@ } }, "bike_themed_object": { + "description": "Eine Ebene mit Objekten zum Thema Fahrrad, die zu keiner anderen Ebene passen", "name": "Weitere fahrradbezogene Objekte", "title": { "mappings": { @@ -1108,8 +1109,7 @@ } }, "render": "Mit Fahrrad zusammenhängendes Objekt" - }, - "description": "Eine Ebene mit Objekten zum Thema Fahrrad, die zu keiner anderen Ebene passen" + } }, "binocular": { "description": "Fernglas", @@ -1156,9 +1156,42 @@ } } }, - "name": "Orte zur Vogelbeobachtung" + "name": "Orte zur Vogelbeobachtung", + "presets": { + "0": { + "description": "Ein überdachter Unterstand, in dem man bequem Vögel beobachten kann" + } + }, + "tagRenderings": { + "bird-hide-wheelchair": { + "mappings": { + "3": { + "then": "Nicht zugänglich für Rollstuhlfahrer" + } + } + }, + "birdhide-operator": { + "mappings": { + "0": { + "then": "Betrieben von Natuurpunt" + }, + "1": { + "then": "Betrieben von einer Forst- bzw. Naturschutzbehörde" + } + }, + "render": "Betrieben von {operator}" + } + } }, "cafe_pub": { + "deletion": { + "extraDeleteReasons": { + "0": { + "explanation": "{title()} wurde dauerhaft geschlossen" + } + } + }, + "description": "Eine Ebene mit Cafés und Kneipen, in denen man sich auf ein Getränk treffen kann. Die Ebene fragt nach einigen relevanten Eigenschaften", "filter": { "0": { "options": { @@ -1171,17 +1204,37 @@ "name": "Cafés und Kneipen", "presets": { "0": { + "description": "Eine Kneipe, in der vor allem Bier in ruhiger, entspannter Atmosphäre getrunken wird", "title": "eine kneipe" }, "1": { + "description": "Eine modernere und kommerzielle Bar, möglicherweise mit einer Musik- und Lichtinstallation", "title": "eine bar" }, "2": { + "description": "Ein Café, um in ruhiger Umgebung Tee, Kaffee oder ein alkoholisches Getränk zu trinken", "title": "eine café" } }, "tagRenderings": { "Classification": { + "mappings": { + "0": { + "then": "Eine Kneipe, in der vor allem Bier in ruhiger, entspannter Atmosphäre getrunken wird" + }, + "1": { + "then": "Eine modernere und kommerzielle Bar, möglicherweise mit einer Musik- und Lichtinstallation" + }, + "2": { + "then": "Ein Café, um in ruhiger Umgebung Tee, Kaffee oder ein alkoholisches Getränk zu trinken" + }, + "3": { + "then": "Ein Restaurant, in dem man ordentlich essen kann" + }, + "4": { + "then": "Ein Außenbereich mit Bierausschank, typischerweise in Deutschland" + } + }, "question": "Was ist das für ein Café" }, "Name": { @@ -1194,7 +1247,8 @@ "0": { "then": "{name}" } - } + }, + "render": "Kneipe" } }, "charging_station": { @@ -1248,11 +1302,18 @@ }, "name": "Ladestationen", "presets": { + "0": { + "title": "eine Ladestation für Elektrofahrräder mit einer normalen europäischen Steckdose (zum Laden von Elektrofahrrädern)" + }, "1": { "title": "eine ladestation für e-bikes" } }, "tagRenderings": { + "Auth phone": { + "question": "Wie lautet die Telefonnummer für den Authentifizierungsanruf oder die SMS?", + "render": "Authentifizierung durch Anruf oder SMS an {authentication:phone_call:number}" + }, "Authentication": { "mappings": { "0": { @@ -1283,6 +1344,104 @@ "question": "Welche Art der Authentifizierung ist an der Ladestation möglich?" }, "Available_charging_stations (generated)": { + "mappings": { + "0": { + "then": "Schuko-Stecker ohne Erdungsstift (CEE7/4 Typ F)" + }, + "1": { + "then": "Schuko-Stecker ohne Erdungsstift (CEE7/4 Typ F)" + }, + "2": { + "then": "Europäischer Netzstecker mit Erdungsstift (CEE7/4 Typ E)" + }, + "3": { + "then": "Europäischer Netzstecker mit Erdungsstift (CEE7/4 Typ E)" + }, + "4": { + "then": "Chademo" + }, + "5": { + "then": "Chademo" + }, + "6": { + "then": "Typ 1 mit Kabel (J1772)" + }, + "7": { + "then": "Typ 1 mit Kabel (J1772)" + }, + "8": { + "then": "Typ 1 ohne Kabel (J1772)" + }, + "9": { + "then": " Typ 1 ohne Kabel (J1772)" + }, + "10": { + "then": "Typ 1 CCS (auch bekannt als Typ 1 Combo)" + }, + "11": { + "then": " Typ 1 CCS (auch bekannt als Typ 1 Combo)" + }, + "12": { + "then": "Tesla Supercharger" + }, + "13": { + "then": "Tesla Supercharger" + }, + "14": { + "then": "Typ 2 (mennekes)" + }, + "15": { + "then": "Typ 2 (mennekes)" + }, + "16": { + "then": "Typ 2 CCS (mennekes)" + }, + "17": { + "then": "Typ 2 CCS (mennekes)" + }, + "18": { + "then": "Typ 2 mit Kabel (mennekes)" + }, + "19": { + "then": "Typ 2 mit Kabel (mennekes)" + }, + "20": { + "then": "Tesla Supercharger CCS (ein Markenzeichen von type2_css)" + }, + "21": { + "then": "Tesla Supercharger CCS (ein Markenzeichen von type2_css)" + }, + "22": { + "then": "Tesla Supercharger (Destination)" + }, + "23": { + "then": "Tesla Supercharger (Destination)" + }, + "24": { + "then": "Tesla supercharger (Destination) (Typ 2 mit Kabel von Tesla)" + }, + "25": { + "then": "Tesla supercharger (Destination) (Typ 2 mit Kabel von Tesla)" + }, + "26": { + "then": "USB zum Aufladen von Handys und kleinen Elektrogeräten" + }, + "27": { + "then": "USB zum Aufladen von Handys und kleinen Elektrogeräten" + }, + "28": { + "then": "Bosch Active Connect mit 3 Pins und Kabel" + }, + "29": { + "then": " Bosch Active Connect mit 3 Pins und Kabel" + }, + "30": { + "then": "Bosch Active Connect mit 5 Pins und Kabel" + }, + "31": { + "then": " Bosch Active Connect mit 5 Pins und Kabel" + } + }, "question": "Welche Ladeanschlüsse gibt es hier?" }, "Network": { @@ -1365,11 +1524,14 @@ }, "question": "Welche Fahrzeuge dürfen hier laden?" }, - "capacity": { - "render": "{capacity} Fahrzeuge können hier gleichzeitig laden" - }, "access": { "mappings": { + "0": { + "then": "Jeder kann diese Ladestation nutzen (eventuell gegen Bezahlung)" + }, + "1": { + "then": "Jeder kann diese Ladestation nutzen (eventuell gegen Bezahlung)" + }, "2": { "then": "Nur Kunden des Ortes, zu dem diese Station gehört, können diese Ladestation nutzen
    Z.B. eine von einem Hotel betriebene Ladestation, die nur von dessen Gästen genutzt werden kann" }, @@ -1380,20 +1542,267 @@ "then": "Nicht für die Allgemeinheit zugänglich (z. B. nur für die Eigentümer, Mitarbeiter, ...)" } }, - "question": "Wer darf diese Ladestation benutzen?" + "question": "Wer darf diese Ladestation benutzen?", + "render": "Zugang ist {access}" + }, + "capacity": { + "question": "Wie viele Fahrzeuge können hier gleichzeitig geladen werden?", + "render": "{capacity} Fahrzeuge können hier gleichzeitig laden" }, "charge": { + "question": "Wie viel muss man für die Nutzung dieser Ladestation bezahlen?", "render": "Die Nutzung dieser Ladestation kostet {charge}" }, + "email": { + "question": "Wie lautet die E-Mail-Adresse des Betreibers?", + "render": "Bei Problemen senden Sie bitte eine E-Mail an {email}" + }, "fee": { "mappings": { + "0": { + "then": "Kostenlos nutzbar (ohne Authentifizierung)" + }, + "1": { + "then": "Kostenlose Nutzung, aber man muss sich authentifizieren" + }, + "2": { + "then": "Kostenlose Nutzung" + }, + "3": { + "then": "Kostenpflichtige Nutzung, aber kostenlos für Kunden des Hotels / Pub / Krankenhauses / ... wer die Ladestation betreibt" + }, "4": { "then": "Nutzung gebührenpflichtig" } - } + }, + "question": "Muss man für die Nutzung dieser Ladestation bezahlen?" + }, + "maxstay": { + "mappings": { + "0": { + "then": "Keine Höchstparkdauer" + } + }, + "question": "Wie lange darf man hier maximal parken?", + "render": "Die maximale Parkdauer beträgt {canonical(maxstay)}" + }, + "phone": { + "question": "Welche Nummer kann man anrufen, wenn es ein Problem mit dieser Ladestation gibt?", + "render": "Bei Problemen, anrufen unter {phone}" + }, + "plugs-0": { + "question": "Wie viele Stecker vom Typ
    Schuko-Stecker ohne Erdungsstift (CEE7/4 Typ F)
    sind hier vorhanden?", + "render": "Hier sind {socket:schuko} Stecker des Typs
    Schuko-Stecker ohne Erdungsstift (CEE7/4 Typ F)
    vorhanden" + }, + "plugs-1": { + "question": "Wie viele Stecker des Typs
    Europäischer Wandstecker mit Erdungsstift (CEE7/4 Typ E)
    sind hier vorhanden?", + "render": "Hier sind {socket:typee} Stecker des Typs
    Europäischer Wandstecker mit Erdungsstift (CEE7/4 Typ E)
    vorhanden" + }, + "voltage-12": { + "render": "
    Tesla Supercharger (Destination) (Typ 2 mit Kabel von Tesla)
    liefert {socket:tesla_destination:voltage} Volt" + }, + "voltage-13": { + "mappings": { + "0": { + "then": "USB zum Aufladen von Handys und kleinen Elektrogeräten liefert 5 Volt" + } + }, + "question": "Welche Spannung liefern die Stecker mit
    USB zum Laden von Handys und kleinen Elektrogeräten
    ?", + "render": "
    USB zum Aufladen von Telefonen und kleinen Elektrogeräten
    liefert {socket:USB-A:voltage} Volt" + }, + "voltage-14": { + "question": "Welche Spannung bieten die Stecker mit
    Bosch Active Connect mit 3 Pins und Kabel
    ?" } } }, + "climbing": { + "description": "Eine Klettergelegenheit", + "name": "Klettermöglichkeiten", + "presets": { + "0": { + "description": "Eine Klettergelegenheit", + "title": "eine klettermöglichkeit" + } + }, + "tagRenderings": { + "Contained routes hist": { + "render": "

    Schwierigkeitsübersicht

    {histogram(_difficulty_hist)}" + }, + "Contained routes length hist": { + "render": "

    Längenübersicht

    {histogram(_length_hist)}" + }, + "Contained_climbing_routes": { + "render": "

    Enthält {_contained_climbing_routes_count} Routen

      {_contained_climbing_routes}
    " + }, + "Rock type (crag/rock/cliff only)": { + "mappings": { + "0": { + "then": "Kalkstein" + } + }, + "question": "Welchen Gesteinstyp gibt es hier?", + "render": "Der Gesteinstyp ist {rock}" + }, + "Type": { + "mappings": { + "0": { + "then": "Ein Kletterfelsen - ein einzelner Felsen oder eine Klippe mit einer oder wenigen Kletterrouten, die ohne Seil sicher bestiegen werden können" + }, + "1": { + "then": "Ein Kletterfelsen - ein einzelner Fels oder eine Klippe mit mindestens einigen Kletterrouten" + } + } + }, + "name": { + "mappings": { + "0": { + "then": "Diese Klettergelegenheit hat keinen Namen" + } + }, + "question": "Wie heißt diese Klettergelegenheit?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Klettergarten {name}" + }, + "1": { + "then": "Klettergebiet {name}" + }, + "2": { + "then": "Klettergebiet" + }, + "3": { + "then": "Klettermöglichkeit {name}" + } + }, + "render": "Klettermöglichkeit" + } + }, + "climbing_club": { + "description": "Ein Kletterverein oder -organisation", + "name": "Klettervereine", + "presets": { + "0": { + "description": "Ein Kletterverein", + "title": "eine kletterverein" + }, + "1": { + "description": "Eine Organisation, die sich mit dem Klettern beschäftigt", + "title": "Eine Kletterorganisation" + } + }, + "tagRenderings": { + "climbing_club-name": { + "question": "Wie lautet der Name dieses Vereins oder Organisation?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Kletter-Organisation" + } + }, + "render": "Kletterverein" + } + }, + "climbing_gym": { + "description": "Eine Kletterhalle", + "name": "Kletterhallen", + "tagRenderings": { + "name": { + "question": "Wie heißt diese Kletterhalle?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Kletterhalle {name}" + } + }, + "render": "Kletterhalle" + } + }, + "climbing_opportunity": { + "description": "Eine Klettergelegenheit?", + "name": "Klettermöglichkeiten?", + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + }, + "climbing-possible": { + "mappings": { + "0": { + "then": "Hier kann geklettert werden" + }, + "1": { + "then": "Hier kann nicht geklettert werden" + }, + "2": { + "then": "Hier kann nicht geklettert werden" + } + }, + "question": "Kann hier geklettert werden?" + } + }, + "title": { + "render": "Klettermöglichkeit?" + } + }, + "climbing_route": { + "name": "Kletterrouten", + "presets": { + "0": { + "title": "eine kletterroute" + } + }, + "tagRenderings": { + "Bolts": { + "mappings": { + "0": { + "then": "Auf dieser Kletterroute sind keine Haken vorhanden" + }, + "1": { + "then": "Auf dieser Kletterroute sind keine Haken vorhanden" + } + }, + "question": "Wie viele Haken gibt es auf dieser Kletterroute bevor der Umlenker bzw. Standhaken erreicht ist?", + "render": "Diese Kletterroute hat {climbing:bolts} Haken" + }, + "Difficulty": { + "question": "Wie hoch ist der Schwierigkeitsgrad dieser Kletterroute nach dem französisch/belgischen System?", + "render": "Die Schwierigkeit ist {climbing:grade:french} entsprechend des französisch/belgischen Systems" + }, + "Length": { + "question": "Wie lang ist diese Kletterroute (in Metern)?", + "render": "Diese Route ist {canonical(climbing:length)} lang" + }, + "Name": { + "mappings": { + "0": { + "then": "Diese Kletterroute hat keinen Namen" + } + }, + "question": "Wie heißt diese Kletterroute?", + "render": "{name}" + }, + "Rock type": { + "render": "Der Gesteinstyp ist {_embedding_features_with_rock:rock}, wie auf dem umgebenden Felsen angegeben" + } + }, + "title": { + "mappings": { + "0": { + "then": "Kleterroute {name}" + } + }, + "render": "Kleterroute" + } + }, "crossings": { "description": "Übergänge für Fußgänger und Radfahrer", "name": "Kreuzungen", @@ -2033,6 +2442,9 @@ "description": "Alle Objekte, die eine bekannte Namensherkunft haben", "name": "Objekte mit Informationen zur Namensherkunft", "tagRenderings": { + "etymology_multi_apply": { + "render": "{multi_apply(_same_name_ids, name:etymology:wikidata;name:etymology, Automatische Datenübernahme auf alle Segmente mit demselben Namen, true)}" + }, "simple etymology": { "mappings": { "0": { @@ -2050,7 +2462,7 @@ }, "extinguisher": { "description": "Kartenebene zur Anzeige von Hydranten.", - "name": "Feuerlöscher anzeigen", + "name": "Feuerlöscher anzeigen.", "presets": { "0": { "description": "Ein Feuerlöscher ist ein kleines, tragbares Gerät, das dazu dient, ein Feuer zu löschen", @@ -2199,6 +2611,9 @@ }, "question": "Wenn Sie Ihr eigenes Behältnis mitbringen (z. B. einen Kochtopf und kleine Töpfe), wird es dann zum Verpacken Ihrer Bestellung verwendet?
    " }, + "friture-vegetarian": { + "question": "Hat dieser Frittenladen vegetarische Snacks?" + }, "halal (no friture)": { "mappings": { "0": { @@ -2228,10 +2643,12 @@ "2": { "then": "Schnellrestaurant" } - } + }, + "render": "Restaurant" } }, "ghost_bike": { + "description": "Eine Ebene mit Gedenkstätten für Radfahrer, die bei Verkehrsunfällen ums Leben gekommen sind", "name": "Geisterräder", "presets": { "0": { @@ -2249,7 +2666,7 @@ "ghost_bike-name": { "mappings": { "0": { - "then": "Auf dem Fahrrad ist kein Name angegeben" + "then": "Am Fahrrad ist kein Name angegeben" } }, "question": "An wen erinnert dieses Geisterrad?
    Bitte respektieren Sie die Privatsphäre - geben Sie den Namen nur an, wenn er weit verbreitet oder auf dem Fahrrad markiert ist. Den Familiennamen können Sie weglassen.
    ", @@ -2274,7 +2691,75 @@ } }, "gps_track": { - "name": "Zurückgelegte Strecke anzeigen" + "name": "Zurückgelegte Strecke anzeigen", + "tagRenderings": { + "Privacy notice": { + "render": "Dies ist der Weg, den Sie seit dem Besuch dieser Webseite zurückgelegt haben. Keine Sorge - diese Daten sind nur für Sie sichtbar und für niemanden sonst. Ihre Standortdaten werden niemals an ein anderes Gerät gesendet." + } + } + }, + "hackerspace": { + "description": "Hackerspace", + "name": "Hackerspaces", + "presets": { + "0": { + "description": "Ein Hackerspace ist ein Ort, an dem sich Menschen treffen, die sich für Software interessieren", + "title": "eine hackerspace" + }, + "1": { + "description": "Ein Makerspace ist ein Ort, an dem Heimwerker-Enthusiasten zusammenkommen, um mit Elektronik zu experimentieren, wie Arduino, LED-Strips, ...", + "title": "eine makerspace" + } + }, + "tagRenderings": { + "hackerspaces-name": { + "question": "Wie lautet der Name dieses Hackerspace?", + "render": "Dieser Hackerspace heißt {name}" + }, + "hackerspaces-opening_hours": { + "mappings": { + "0": { + "then": "durchgehend geöffnet" + } + }, + "question": "Wann hat dieser Hackerspace geöffnet?", + "render": "{opening_hours_table()}" + }, + "hackerspaces-start_date": { + "question": "Wann wurde dieser Hackerspace gegründet?", + "render": "Dieser Hackerspace wurde gegründet am {start_date}" + }, + "hs-club-mate": { + "mappings": { + "0": { + "then": "In diesem Hackerspace gibt es Club Mate" + }, + "1": { + "then": "In diesem Hackerspace gibt es kein Club Mate" + } + }, + "question": "Gibt es in diesem Hackerspace Club Mate?" + }, + "is_makerspace": { + "mappings": { + "0": { + "then": "Dies ist ein Makerspace" + }, + "1": { + "then": "Dies ist ein traditioneller (softwareorientierter) Hackerspace" + } + }, + "question": "Ist dies ein Hackerspace oder ein Makerspace?" + } + }, + "title": { + "mappings": { + "0": { + "then": " {name}" + } + }, + "render": "Hackerspace" + } }, "hydrant": { "description": "Kartenebene zur Anzeige von Hydranten.", @@ -2342,6 +2827,7 @@ } }, "information_board": { + "description": "Eine Ebene mit touristischen, straßenseitigen Informationstafeln (z. B. mit Informationen über die Landschaft, ein Gebäude, ein Merkmal, eine Karte, ...)", "name": "Informationstafeln", "presets": { "0": { @@ -2407,6 +2893,9 @@ }, "1": { "options": { + "0": { + "question": "Alle Naturschutzgebiete" + }, "1": { "question": "Hunde dürfen frei herumlaufen" }, @@ -2417,7 +2906,37 @@ } }, "name": "Naturschutzgebiete", + "presets": { + "0": { + "description": "Ein fehlendes Naturschutzgebiet hinzufügen", + "title": "ein Naturschutzgebiet" + } + }, "tagRenderings": { + "Access tag": { + "mappings": { + "0": { + "then": "Öffentlich zugänglich" + }, + "1": { + "then": "Nicht zugänglich" + }, + "2": { + "then": "Nicht zugänglich, da dies ein privater Bereich ist" + }, + "3": { + "then": "Zugänglich, obwohl es sich um ein privates Gebiet handelt" + }, + "4": { + "then": "Nur mit einem Führer oder bei organisierten Aktivitäten zugänglich" + }, + "5": { + "then": "Zugänglich gegen Gebühr" + } + }, + "question": "Ist dieses Naturschutzgebiet für die Öffentlichkeit zugänglich?", + "render": "Zugang zu diesem Naturschutzgebiet: {access:description}" + }, "Curator": { "question": "Wer ist der Verwalter dieses Naturschutzgebietes?
    Respektieren Sie die Privatsphäre - geben Sie nur dann einen Namen an, wenn dieser allgemein bekannt ist", "render": "{curator} ist der Pfleger dieses Naturschutzgebietes" @@ -2436,20 +2955,155 @@ }, "question": "Sind Hunde in diesem Naturschutzgebiet erlaubt?" }, + "Editable description": { + "question": "Gibt es zusätzliche Informationen?", + "render": "Zusätzliche Informationen: {description:0}" + }, "Email": { "question": "An welche Email-Adresse kann man sich bei Fragen und Problemen zu diesem Naturschutzgebiet wenden?
    Respektieren Sie die Privatsphäre - geben Sie nur dann eine persönliche Email-Adresse an, wenn diese allgemein bekannt ist", "render": "{email}" }, + "Name tag": { + "mappings": { + "0": { + "then": "Dieses Gebiet hat keinen Namen" + } + }, + "question": "Wie heißt dieses Gebiet?", + "render": "Dieses Gebiet heißt {name}" + }, + "Non-editable description": { + "render": "Zusätzliche Informationen: {description}" + }, + "Operator tag": { + "mappings": { + "0": { + "then": "Betrieben von Natuurpunt" + }, + "1": { + "then": "Betrieben von {operator}" + }, + "2": { + "then": "Betrieben von Agentschap Natuur en Bos" + } + }, + "question": "Wer betreibt dieses Gebiet?", + "render": "Betrieben von {operator}" + }, "Surface area": { "render": "Grundfläche: {_surface:ha}ha" }, "phone": { "question": "Welche Telefonnummer kann man bei Fragen und Problemen zu diesem Naturschutzgebiet anrufen?
    Respektieren Sie die Privatsphäre - geben Sie nur eine Telefonnummer an, wenn diese allgemein bekannt ist" } + }, + "title": { + "render": "Naturschutzgebiet" } }, "note": { - "name": "OpenStreetMap-Hinweise" + "filter": { + "0": { + "options": { + "0": { + "question": "Sollte {search} im ersten Kommentar erwähnen" + } + } + }, + "1": { + "options": { + "0": { + "question": "Sollte nicht {search} im ersten Kommentar erwähnen" + } + } + }, + "2": { + "options": { + "0": { + "question": "Geöffnet vom Mitwirkenden {search}" + } + } + }, + "3": { + "options": { + "0": { + "question": "Nicht vom Mitwirkenden {search} geöffnet" + } + } + }, + "4": { + "options": { + "0": { + "question": "Zuletzt bearbeitet vom Mitwirkenden {search}" + } + } + }, + "5": { + "options": { + "0": { + "question": "Geöffnet nach {search}" + } + } + }, + "6": { + "options": { + "0": { + "question": "Erstellt vor {search}" + } + } + }, + "7": { + "options": { + "0": { + "question": "Erstellt nach {search}" + } + } + }, + "8": { + "options": { + "0": { + "question": "Nur Notizen anzeigen, die von anonymen Mitwirkenden geöffnet wurden" + } + } + }, + "9": { + "options": { + "0": { + "question": "Nur offene Notizen anzeigen" + } + } + }, + "10": { + "options": { + "0": { + "question": "Importnotizen ausblenden" + } + } + } + }, + "name": "OpenStreetMap-Hinweise", + "tagRenderings": { + "report-contributor": { + "render": "{_first_user} als Spam melden" + }, + "report-note": { + "render": "Diese Notiz als Spam oder unangemessen melden" + } + }, + "title": { + "mappings": { + "0": { + "then": "Geschlossene Notiz" + } + }, + "render": "Notiz" + } + }, + "note_import": { + "name": "Mögliche Bücherschränke", + "title": { + "render": "Mögliches Objekt" + } }, "observation_tower": { "description": "Türme zur Aussicht auf die umgebende Landschaft", @@ -2472,6 +3126,28 @@ "question": "Wer betreibt diesen Turm?", "render": "Betrieben von {operator}" }, + "access": { + "mappings": { + "0": { + "then": "Dieser Turm ist öffentlich zugänglich" + }, + "1": { + "then": "Dieser Turm kann nur mit einem Führer besichtigt werden" + } + }, + "question": "Kann dieser Turm besichtigt werden?" + }, + "elevator": { + "mappings": { + "0": { + "then": "Dieser Turm verfügt über einen Aufzug, der die Besucher nach oben bringt" + }, + "1": { + "then": "Dieser Turm hat keinen Aufzug" + } + }, + "question": "Hat dieser Turm einen Aufzug?" + }, "name": { "mappings": { "0": { @@ -2480,6 +3156,10 @@ }, "question": "Wie heißt dieser Turm?", "render": "Der Name dieses Turms lautet {name}" + }, + "step_count": { + "question": "Wie viele einzelne Stufen muss man erklimmen, um die Spitze des Turms zu erreichen?", + "render": "Dieser Turm hat {step_count} Stufen, um die Spitze zu erreichen" } }, "title": { @@ -2501,7 +3181,16 @@ } }, "parking": { - "name": "Parkplätze" + "description": "Eine Ebene mit Parkplätzen", + "name": "Parkplätze", + "presets": { + "0": { + "title": "ein Parkplatz" + } + }, + "title": { + "render": "Parkplatz" + } }, "pedestrian_path": { "name": "Fußgängerwege" @@ -2560,6 +3249,9 @@ "0": { "then": "Zugänglich für die Allgemeinheit" }, + "1": { + "then": "Dies ist ein gebührenpflichtiger Spielplatz" + }, "2": { "then": "Nur für Kunden des Betreibers zugänglich" }, @@ -2768,6 +3460,7 @@ } }, "recycling": { + "description": "Eine Ebene mit Recyclingcontainern und -zentren", "filter": { "0": { "options": { @@ -2775,11 +3468,217 @@ "question": "Derzeit geöffnet" } } + }, + "1": { + "options": { + "0": { + "question": "Alle Recyclingarten" + }, + "1": { + "question": "Recycling von Batterien" + }, + "2": { + "question": "Recycling von Getränkekartons" + }, + "3": { + "question": "Recycling von Dosen" + }, + "4": { + "question": "Recycling von Kleidung" + }, + "5": { + "question": "Recycling von Speiseöl" + }, + "6": { + "question": "Recycling von Motoröl" + }, + "7": { + "question": "Recycling von Grünabfällen" + }, + "8": { + "question": "Recycling von Glasflaschen" + }, + "9": { + "question": "Recycling von Glas" + }, + "10": { + "question": "Recycling von Zeitungen" + }, + "11": { + "question": "Recycling von Papier" + }, + "12": { + "question": "Recycling von Plastikflaschen" + }, + "13": { + "question": "Recycling von Kunststoffverpackungen" + }, + "14": { + "question": "Recycling von Kunststoffen" + }, + "15": { + "question": "Recycling von Metallschrott" + }, + "16": { + "question": "Recycling von Elektrokleingeräten" + }, + "17": { + "question": "Recycling von Restabfällen" + } + } } }, - "name": "Recycling" + "name": "Recycling", + "presets": { + "0": { + "title": "ein Recyclingcontainer" + }, + "1": { + "title": "ein Wertstoffhof" + } + }, + "tagRenderings": { + "container-location": { + "mappings": { + "0": { + "then": "Dies ist ein Unterflurcontainer" + }, + "1": { + "then": "Dieser Container befindet sich in einem Gebäude" + }, + "2": { + "then": "Dieser Container befindet sich im Freien" + } + }, + "question": "Wo befindet sich dieser Container?" + }, + "opening_hours": { + "mappings": { + "0": { + "then": "24/7" + } + }, + "question": "Wie sind die Öffnungszeiten dieser Recyclinganlage?" + }, + "operator": { + "question": "Welches Unternehmen betreibt diese Recyclinganlage?", + "render": "Diese Recyclinganlage wird betrieben von {operator}" + }, + "recycling-accepts": { + "mappings": { + "0": { + "then": "Batterien können hier recycelt werden" + }, + "1": { + "then": "Getränkekartons können hier recycelt werden" + }, + "2": { + "then": "Dosen können hier recycelt werden" + }, + "3": { + "then": "Kleidung kann hier recycelt werden" + }, + "4": { + "then": "Speiseöl kann hier recycelt werden" + }, + "5": { + "then": "Motoröl kann hier recycelt werden" + }, + "6": { + "then": "Grünabfälle können hier recycelt werden" + }, + "7": { + "then": "Bio-Abfall kann hier recycelt werden" + }, + "8": { + "then": "Glasflaschen können hier recycelt werden" + }, + "9": { + "then": "Glas kann hier recycelt werden" + }, + "10": { + "then": "Zeitungen können hier recycelt werden" + }, + "11": { + "then": "Papier kann hier recycelt werden" + }, + "12": { + "then": "Plastikflaschen können hier recycelt werden" + }, + "13": { + "then": "Kunststoffverpackungen können hier recycelt werden" + }, + "14": { + "then": "Kunststoff kann hier recycelt werden" + }, + "15": { + "then": "Metallschrott kann hier recycelt werden" + }, + "16": { + "then": "Schuhe können hier recycelt werden" + }, + "17": { + "then": "Elektrokleingeräte können hier recycelt werden" + }, + "18": { + "then": "Elektrokleingeräte können hier recycelt werden" + }, + "19": { + "then": "Nadeln können hier recycelt werden" + }, + "20": { + "then": "Restmüll kann hier recycelt werden" + } + }, + "question": "Was kann hier recycelt werden?" + }, + "recycling-centre-name": { + "mappings": { + "0": { + "then": "Dieser Wertstoffhof hat keinen bestimmten Namen" + } + }, + "question": "Wie lautet der Name dieses Wertstoffhofs?", + "render": "Dieser Wertstoffhof heißt {name}" + }, + "recycling-type": { + "mappings": { + "0": { + "then": "Dies ist ein Recycling-Container" + }, + "1": { + "then": "Dies ist ein Wertstoffhof" + }, + "2": { + "then": "Dies ist ein Abfallcontainer für Restmüll" + } + }, + "question": "Um welche Recyclingeinrichtung handelt es sich?" + } + }, + "title": { + "mappings": { + "0": { + "then": "Wertstoffhof" + }, + "1": { + "then": "Wertstoffhof" + }, + "2": { + "then": "Recyclingcontainer" + } + }, + "render": "Recyclinganlage" + } }, "shops": { + "deletion": { + "extraDeleteReasons": { + "0": { + "explanation": "{title()} wurde dauerhaft geschlossen" + } + } + }, "description": "Ein Geschäft", "filter": { "0": { @@ -2806,13 +3705,15 @@ }, "tagRenderings": { "shops-email": { - "question": "Wie ist die Email-Adresse dieses Geschäfts?" + "question": "Wie ist die Email-Adresse dieses Geschäfts?", + "render": "{email}" }, "shops-name": { "question": "Wie ist der Name dieses Geschäfts?" }, "shops-opening_hours": { - "question": "Wie sind die Öffnungszeiten dieses Geschäfts?" + "question": "Wie sind die Öffnungszeiten dieses Geschäfts?", + "render": "{opening_hours_table(opening_hours)}" }, "shops-phone": { "question": "Wie ist die Telefonnummer?", @@ -2863,6 +3764,7 @@ } }, "slow_roads": { + "description": "Alle autofreien Straßen", "tagRenderings": { "slow_roads-surface": { "mappings": { @@ -3006,10 +3908,165 @@ } }, "street_lamps": { - "name": "Straßenlaternen" + "description": "Eine Ebene mit Straßenbeleuchtung", + "name": "Straßenlaternen", + "presets": { + "0": { + "title": "eine Straßenlaterne" + } + }, + "tagRenderings": { + "colour": { + "mappings": { + "0": { + "then": "Diese Lampe strahlt weißes Licht aus" + }, + "1": { + "then": "Diese Lampe strahlt grünes Licht aus" + }, + "2": { + "then": "Diese Lampe strahlt orangefarbenes Licht aus" + } + }, + "question": "Welche Lichtfarbe strahlt diese Lampe aus?", + "render": "Diese Lampe strahlt {light:colour} Licht aus" + }, + "count": { + "mappings": { + "0": { + "then": "Diese Straßenlaterne hat 1 Leuchte" + }, + "1": { + "then": "Diese Straßenlaterne hat 2 Leuchten" + } + }, + "question": "Wie viele Leuchten hat diese Straßenlaterne?", + "render": "Diese Straßenlaterne hat {light:count} Leuchten" + }, + "direction": { + "question": "Wohin leuchtet diese Straßenlaterne?", + "render": "Diese Straßenlaterne leuchtet in Richtung {light:direction}" + }, + "lamp_mount": { + "mappings": { + "0": { + "then": "Diese Straßenlaterne sitzt auf einem geraden Mast" + }, + "1": { + "then": "Diese Straßenlaterne sitzt am Ende eines gebogenen Mastes" + } + }, + "question": "Wie ist diese Straßenlaterne am Mast befestigt?" + }, + "lit": { + "mappings": { + "0": { + "then": "Diese Straßenlaterne leuchtet nachts" + }, + "1": { + "then": "Diese Straßenlaterne leuchtet durchgehend" + }, + "2": { + "then": "Diese Straßenlaterne leuchtet bewegungsgesteuert" + }, + "3": { + "then": "Diese Straßenlaterne leuchtet bei Bedarf (z. B. mit einem Taster)" + } + }, + "question": "Wann leuchtet diese Straßenlaterne?" + }, + "method": { + "mappings": { + "0": { + "then": "Diese Straßenlaterne leuchtet elektrisch" + }, + "1": { + "then": "Diese Straßenlaterne verwendet LEDs" + }, + "2": { + "then": "Diese Straßenlaterne verwendet Glühlampenlicht" + }, + "3": { + "then": "Diese Straßenlaterne verwendet Halogenlicht" + }, + "4": { + "then": "Diese Straßenlaterne verwendet Entladungslampen (unbekannter Typ)" + }, + "5": { + "then": "Diese Straßenlaterne verwendet eine Quecksilberdampflampe (leicht bläulich)" + }, + "6": { + "then": "Diese Straßenlaterne verwendet Halogen-Metalldampflampen (hellweiß)" + }, + "7": { + "then": "Diese Straßenlaterne verwendet Leuchtstoffröhren" + }, + "8": { + "then": "Diese Straßenlaterne verwendet Natriumdampflampen (unbekannter Typ)" + }, + "9": { + "then": "Diese Straßenlaterne verwendet Niederdruck-Natriumdampflampen (einfarbig orange)" + }, + "10": { + "then": "Diese Straßenlaterne verwendet Hochdruck-Natriumdampflampen (orange mit weiß)" + }, + "11": { + "then": "Diese Straßenlaterne wird mit Gas beleuchtet" + } + }, + "question": "Mit welcher Art von Beleuchtung arbeitet diese Straßenlaterne?" + }, + "ref": { + "question": "Wie lautet die Referenznummer dieser Straßenlaterne?", + "render": "Diese Straßenlaterne hat die Referenznummer {ref}" + }, + "support": { + "mappings": { + "0": { + "then": "Diese Straßenlaterne ist an einem Kabel aufgehängt" + }, + "1": { + "then": "Diese Straßenlaterne ist an einer Decke montiert" + }, + "2": { + "then": "Diese Straßenlaterne ist im Boden montiert" + }, + "3": { + "then": "Diese Straßenlaterne ist an einem kurzen Mast (< 1,5m) montiert" + }, + "4": { + "then": "Diese Straßenlaterne ist an einem Mast montiert" + }, + "5": { + "then": "Diese Straßenlaterne ist direkt an der Wand montiert" + }, + "6": { + "then": "Diese Straßenlaterne ist mit einer Metallstange an der Wand montiert" + } + }, + "question": "Wie ist diese Straßenlaterne befestigt?" + } + }, + "title": { + "mappings": { + "0": { + "then": "Straßenlaterne {ref}" + } + }, + "render": "Straßenlaterne" + } }, "surveillance_camera": { + "description": "Diese Ebene zeigt die Überwachungskameras an und ermöglicht es, Informationen zu aktualisieren und neue Kameras hinzuzufügen", "name": "Überwachungskameras", + "presets": { + "0": { + "title": "eine Überwachungskamera" + }, + "1": { + "title": "eine an einer Wand montierte Überwachungskamera" + } + }, "tagRenderings": { "Camera type: fixed; panning; dome": { "mappings": { @@ -3087,7 +4144,13 @@ "render": "Montageart: {camera:mount}" }, "camera_direction": { - "question": "In welche Himmelsrichtung ist diese Kamera ausgerichtet?" + "mappings": { + "0": { + "then": "filmt in Himmelsrichtung {direction}" + } + }, + "question": "In welche Himmelsrichtung ist diese Kamera ausgerichtet?", + "render": "filmt in Himmelsrichtung {camera:direction}" }, "is_indoor": { "mappings": { @@ -3109,6 +4172,7 @@ } }, "toilet": { + "description": "Eine Ebene mit (öffentlichen) Toiletten", "filter": { "0": { "options": { @@ -3150,6 +4214,14 @@ } }, "tagRenderings": { + "Opening-hours": { + "mappings": { + "0": { + "then": "Durchgehend geöffnet" + } + }, + "question": "Wann sind diese Toiletten geöffnet?" + }, "toilet-access": { "mappings": { "0": { @@ -3206,6 +4278,9 @@ }, "toilet-has-paper": { "mappings": { + "0": { + "then": "Diese Toilette ist mit Toilettenpapier ausgestattet" + }, "1": { "then": "Für diese Toilette müssen Sie Ihr eigenes Toilettenpapier mitbringen" } @@ -3295,6 +4370,7 @@ } }, "tree_node": { + "description": "Eine Ebene, die Bäume zeigt", "name": "Bäume", "presets": { "0": { @@ -3336,9 +4412,15 @@ "3": { "then": "Der Baum steht in einem Park oder ähnlichem (Friedhof, Schulgelände, ...)." }, + "4": { + "then": "Der Baum steht in einem Wohngarten." + }, "5": { "then": "Dieser Baum steht entlang einer Straße." }, + "6": { + "then": "Der Baum steht in einem städtischen Gebiet." + }, "7": { "then": "Dieser Baum steht außerhalb eines städtischen Gebiets." } @@ -3397,7 +4479,8 @@ "render": "Name: {name}" }, "tree_node-ref:OnroerendErfgoed": { - "question": "Wie lautet die Kennung der Onroerend Erfgoed Flanders?" + "question": "Wie lautet die Kennung der Onroerend Erfgoed Flanders?", + "render": "\"\"/ Onroerend Erfgoed Kennung: {ref:OnroerendErfgoed}" }, "tree_node-wikidata": { "question": "Was ist das passende Wikidata Element zu diesem Baum?", @@ -3425,6 +4508,9 @@ "render": "Aussichtspunkt" } }, + "village_green": { + "description": "Eine Ebene mit Dorfangern (kommunale Grünflächen, aber nicht wirklich Parks)" + }, "visitor_information_centre": { "description": "Ein Besucherzentrum bietet Informationen über eine bestimmte Attraktion oder Sehenswürdigkeit, an der es sich befindet.", "name": "Besucherinformationszentrum", @@ -3437,6 +4523,12 @@ "render": "{name}" } }, + "walls_and_buildings": { + "description": "Spezielle eingebaute Ebene, die alle Wände und Gebäude bereitstellt. Diese Ebene ist in Voreinstellungen für Objekte nützlich, die an Wänden platziert werden können (z. B. AEDs, Briefkästen, Eingänge, Adressen, Überwachungskameras, ...). Diese Ebene ist standardmäßig unsichtbar und kann vom Benutzer nicht umgeschaltet werden.", + "title": { + "render": "Wand oder Gebäude" + } + }, "waste_basket": { "description": "Dies ist ein öffentlicher Abfalleimer, in den Sie Ihren Müll entsorgen können.", "filter": { @@ -3536,7 +4628,123 @@ "render": "Abfalleimer" } }, + "waste_disposal": { + "description": "Entsorgungsbehälter, mittlerer bis großer Behälter zur Entsorgung von (Haushalts-)Abfällen", + "filter": { + "0": { + "options": { + "0": { + "question": "Nur öffentlich zugänglich" + } + } + } + }, + "name": "Mülleimer", + "presets": { + "0": { + "description": "Mittlere bis große Mülltonne für die Entsorgung von (Haushalts-)Abfällen", + "title": "ein Abfalleimer" + } + }, + "tagRenderings": { + "access": { + "mappings": { + "0": { + "then": "Dieser Behälter kann von jedem benutzt werden" + }, + "1": { + "then": "Dieser Behälter ist privat" + }, + "2": { + "then": "Diese Mülltonne ist nur für Anwohner" + } + }, + "question": "Wer kann diese Mülltonne benutzen?", + "render": "Zugang: {access}" + }, + "disposal-location": { + "mappings": { + "0": { + "then": "Dies ist ein unterirdischer Container" + }, + "1": { + "then": "Dieser Container befindet sich in einem Gebäude" + }, + "2": { + "then": "Dieser Container befindet sich im Freien" + } + }, + "question": "Wo befindet sich dieser Container?" + } + }, + "title": { + "render": "Abfallentsorgung" + } + }, "watermill": { "name": "Wassermühle" + }, + "windturbine": { + "name": "Windräder", + "presets": { + "0": { + "title": "ein Windrad" + } + }, + "tagRenderings": { + "turbine-diameter": { + "question": "Wie groß ist der Rotordurchmesser der Windturbine in Meter?", + "render": "Der Rotordurchmesser der Windturbine ist {rotor:diameter} Meter." + }, + "turbine-height": { + "question": "Wie hoch ist dieses Windrad (inklusive Rotorradius) in Metern?", + "render": "Die Gesamthöhe dieses Windrads beträgt (einschließlich Rotorradius) {height} Meter." + }, + "turbine-operator": { + "question": "Wer betreibt das Windrads?", + "render": "Die Windturbine wird betrieben von {operator}." + }, + "turbine-output": { + "question": "Wieviel Strom erzeugt das Windrad? (z.B. 2.3MW)", + "render": "Das Windrad erzeugt {generator:output:electricity} Strom." + }, + "turbine-start-date": { + "question": "Wann wurde das Windrad in Betrieb genommen?", + "render": "Das Windrad wurde am {start_date} in Betrieb genommen." + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "Windrad" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " Megawatt" + }, + "1": { + "human": " Kilowatt" + }, + "2": { + "human": " Watt" + }, + "3": { + "human": " Gigawatt" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " Meter" + } + } + } + } } -} +} \ No newline at end of file diff --git a/langs/layers/en.json b/langs/layers/en.json index 7a6ce846a..aaf6f81d8 100644 --- a/langs/layers/en.json +++ b/langs/layers/en.json @@ -2302,6 +2302,194 @@ } } }, + "climbing": { + "description": "A climbing opportunity", + "name": "Climbing opportunities", + "presets": { + "0": { + "description": "A climbing opportunity", + "title": "a climbing opportunity" + } + }, + "tagRenderings": { + "Contained routes hist": { + "render": "

    Grades overview

    {histogram(_difficulty_hist)}" + }, + "Contained routes length hist": { + "render": "

    Length overview

    {histogram(_length_hist)}" + }, + "Contained_climbing_routes": { + "render": "

    Contains {_contained_climbing_routes_count} routes

      {_contained_climbing_routes}
    " + }, + "Rock type (crag/rock/cliff only)": { + "mappings": { + "0": { + "then": "Limestone" + } + }, + "question": "What is the rock type here?", + "render": "The rock type is {rock}" + }, + "Type": { + "mappings": { + "0": { + "then": "A climbing boulder - a single rock or cliff with one or a few climbing routes which can be climbed safely without rope" + }, + "1": { + "then": "A climbing crag - a single rock or cliff with at least a few climbing routes" + } + } + }, + "name": { + "mappings": { + "0": { + "then": "This climbing opportunity doesn't have a name" + } + }, + "question": "What is the name of this climbing opportunity?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Climbing crag {name}" + }, + "1": { + "then": "Climbing area {name}" + }, + "2": { + "then": "Climbing site" + }, + "3": { + "then": "Climbing opportunity {name}" + } + }, + "render": "Climbing opportunity" + } + }, + "climbing_club": { + "description": "A climbing club or organisation", + "name": "Climbing club", + "presets": { + "0": { + "description": "A climbing club", + "title": "a climbing club" + }, + "1": { + "description": "An NGO working around climbing", + "title": "a climbing ngo" + } + }, + "tagRenderings": { + "climbing_club-name": { + "question": "What is the name of this climbing club or NGO?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Climbing NGO" + } + }, + "render": "Climbing club" + } + }, + "climbing_gym": { + "description": "A climbing gym", + "name": "Climbing gyms", + "tagRenderings": { + "name": { + "question": "What is the name of this climbing gym?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Climbing gym {name}" + } + }, + "render": "Climbing gym" + } + }, + "climbing_opportunity": { + "description": "A climbing opportunity?", + "name": "Climbing opportunities?", + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + }, + "climbing-possible": { + "mappings": { + "0": { + "then": "Climbing is possible here" + }, + "1": { + "then": "Climbing is not possible here" + }, + "2": { + "then": "Climbing is not possible here" + } + }, + "question": "Is climbing possible here?" + } + }, + "title": { + "render": "Climbing opportunity?" + } + }, + "climbing_route": { + "name": "Climbing routes", + "presets": { + "0": { + "title": "a climbing route" + } + }, + "tagRenderings": { + "Bolts": { + "mappings": { + "0": { + "then": "This route is not bolted" + }, + "1": { + "then": "This route is not bolted" + } + }, + "question": "How many bolts does this route have before reaching the anchor?", + "render": "This route has {climbing:bolts} bolts" + }, + "Difficulty": { + "question": "What is the grade of this climbing route according to the french/belgian system?", + "render": "The grade is {climbing:grade:french} according to the french/belgian system" + }, + "Length": { + "question": "How long is this climbing route (in meters)?", + "render": "This route is {canonical(climbing:length)} long" + }, + "Name": { + "mappings": { + "0": { + "then": "This climbing route doesn't have a name" + } + }, + "question": "What is the name of this climbing route?", + "render": "{name}" + }, + "Rock type": { + "render": "The rock type is {_embedding_features_with_rock:rock} as stated on the surrounding crag" + } + }, + "title": { + "mappings": { + "0": { + "then": "Climbing route {name}" + } + }, + "render": "Climbing route" + } + }, "crossings": { "description": "Crossings for pedestrians and cyclists", "name": "Crossings", @@ -3234,7 +3422,7 @@ "title": "a fastfood" }, "2": { - "description": "A fastfood-buisiness focused on french fries", + "description": "A fastfood-business focused on french fries", "title": "a fries shop" } }, @@ -3493,6 +3681,69 @@ "grass_in_parks": { "description": "Searches for all accessible grass patches within public parks - these are 'groenzones'\"" }, + "hackerspace": { + "description": "Hackerspace", + "name": "Hackerspace", + "presets": { + "0": { + "description": "A hackerspace is an area where people interested in software gather", + "title": "a hackerspace" + }, + "1": { + "description": "A makerspace is a place where DIY-enthusiasts gather to experiment with electronics such as arduino, LEDstrips, ...", + "title": "a makerspace" + } + }, + "tagRenderings": { + "hackerspaces-name": { + "question": "What is the name of this hackerspace?", + "render": "This hackerspace is named {name}" + }, + "hackerspaces-opening_hours": { + "mappings": { + "0": { + "then": "Opened 24/7" + } + }, + "question": "When is this hackerspace opened?", + "render": "{opening_hours_table()}" + }, + "hackerspaces-start_date": { + "question": "When was this hackerspace founded?", + "render": "This hackerspace was founded at {start_date}" + }, + "hs-club-mate": { + "mappings": { + "0": { + "then": "This hackerspace serves club mate" + }, + "1": { + "then": "This hackerspace does not serve club mate" + } + }, + "question": "Does this hackerspace serve Club Mate?" + }, + "is_makerspace": { + "mappings": { + "0": { + "then": "This is a makerspace" + }, + "1": { + "then": "This is a traditional (software oriented) hackerspace" + } + }, + "question": "Is this a hackerspace or a makerspace?" + } + }, + "title": { + "mappings": { + "0": { + "then": " {name}" + } + }, + "render": "Hackerspace" + } + }, "hydrant": { "description": "Map layer to show fire hydrants.", "name": "Map of hydrants", @@ -5203,6 +5454,9 @@ }, "question": "Is this a broadleaved or needleleaved tree?" }, + "tree-species-wikidata": { + "question": "What species is this tree?" + }, "tree_node-name": { "mappings": { "0": { @@ -5417,5 +5671,69 @@ }, "watermill": { "name": "Watermill" + }, + "windturbine": { + "description": "Modern windmills generating electricity", + "name": "wind turbine", + "presets": { + "0": { + "title": "a wind turbine" + } + }, + "tagRenderings": { + "turbine-diameter": { + "question": "What is the rotor diameter of this wind turbine, in metres?", + "render": "The rotor diameter of this wind turbine is {rotor:diameter} metres." + }, + "turbine-height": { + "question": "What is the total height of this wind turbine (including rotor radius), in metres?", + "render": "The total height (including rotor radius) of this wind turbine is {height} metres." + }, + "turbine-operator": { + "question": "Who operates this wind turbine?", + "render": "This wind turbine is operated by {operator}." + }, + "turbine-output": { + "question": "What is the power output of this wind turbine? (e.g. 2.3 MW)", + "render": "The power output of this wind turbine is {generator:output:electricity}." + }, + "turbine-start-date": { + "question": "When did this wind turbine go into operation?", + "render": "This wind turbine went into operation on/in {start_date}." + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "wind turbine" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " megawatts" + }, + "1": { + "human": " kilowatts" + }, + "2": { + "human": " watts" + }, + "3": { + "human": " gigawatts" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " meter" + } + } + } + } } -} +} \ No newline at end of file diff --git a/langs/layers/eo.json b/langs/layers/eo.json index 63d58d4a4..be60b846f 100644 --- a/langs/layers/eo.json +++ b/langs/layers/eo.json @@ -188,5 +188,39 @@ "title": "Rubujo" } } + }, + "windturbine": { + "title": { + "mappings": { + "0": { + "then": "{name}" + } + } + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " megavatoj" + }, + "1": { + "human": " kilovatoj" + }, + "2": { + "human": " vatoj" + }, + "3": { + "human": " gigavatoj" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " metro" + } + } + } + } } } \ No newline at end of file diff --git a/langs/layers/es.json b/langs/layers/es.json index 961033fe7..482a0f017 100644 --- a/langs/layers/es.json +++ b/langs/layers/es.json @@ -12,16 +12,67 @@ "then": "Esta edificación no tiene número" } }, - "question": "¿Cuál es el número de esta casa?" + "question": "¿Cuál es el número de esta casa?", + "render": "La numeración de la casa es {addr:housenumber}" }, "street": { - "question": "¿En qué calle se encuentra esta dirección?" + "question": "¿En qué calle se encuentra esta dirección?", + "render": "La dirección está en la calle {addr:street}" } }, "title": { "render": "Domicilio conocido" } }, + "ambulancestation": { + "description": "Una estación de ambulancias es una zona para almacenar vehículos de ambulancia, equipamiento médico, equipos de protección personal y otros suministros médicos.", + "name": "Mapa de estaciones de ambulancias", + "presets": { + "0": { + "description": "Añadir una estación de ambulancias al mapa", + "title": "una estación de ambulancias" + } + }, + "tagRenderings": { + "ambulance-agency": { + "question": "¿Qué agencia opera esta estación?", + "render": "Esta estación la opera {operator}." + }, + "ambulance-name": { + "question": "¿Cual es el nombre de esta estación de ambulancias?", + "render": "Esta estación se llama {name}." + }, + "ambulance-operator-type": { + "mappings": { + "0": { + "then": "La estación la opera el govierno." + }, + "1": { + "then": "La estación la opera una organización basada en la comunidad o informal." + }, + "2": { + "then": "La estación la opera un grupo formal de voluntarios." + }, + "3": { + "then": "La estación es de gestión privada." + } + }, + "question": "¿Como está clasificada la operadora de la estación?", + "render": "La operador a no es una entidad de tipo {operator:type}." + }, + "ambulance-place": { + "question": "¿Dónde se encuentra la estación? (ej. nombre del barrio, pueblo o ciudad)", + "render": "Esta estación se encuentra en {addr:place}." + }, + "ambulance-street": { + "question": " ¿Cual es el nombre de la calle en la que se encuentra la estación?", + "render": "Esta estación se encuentra al lado de una autovía llamada {addr:street}." + } + }, + "title": { + "render": "Estación de Ambulancias" + } + }, "artwork": { "description": "Diversas piezas de obras de arte", "name": "Obras de arte", @@ -31,6 +82,10 @@ } }, "tagRenderings": { + "artwork-artist_name": { + "question": "¿Que artista creó esto?", + "render": "Creado por {artist_name}" + }, "artwork-artwork_type": { "mappings": { "0": { @@ -51,15 +106,35 @@ "5": { "then": "Busto" }, + "6": { + "then": "Piedra" + }, "7": { "then": "Instalación" }, "8": { "then": "Grafiti" + }, + "9": { + "then": "Relieve" + }, + "10": { + "then": "Azulejo (azulejos decorativos españoles)" + }, + "11": { + "then": "Cerámica" } }, "question": "¿Qué tipo de obra es esta pieza?", "render": "Esta es un {artwork_type}" + }, + "artwork-website": { + "question": "¿Hay un sitio web con más información sobre esta obra de arte?", + "render": "Más información en este sitio web" + }, + "artwork-wikidata": { + "question": "¿Qué entrada de Wikidata se corresponde con esta obra de arte?", + "render": "Se corresponde con {wikidata}" } }, "title": { @@ -75,6 +150,7 @@ "name": "Barreras", "presets": { "0": { + "description": "Un bolardo en la carretera", "title": "una bolardo" } }, @@ -92,6 +168,35 @@ } }, "question": "¿Qué tipo de bolardo es este?" + }, + "Cycle barrier type": { + "question": "¿Qué tipo de barrera ciclista es esta?" + }, + "MaxWidth": { + "question": "¿Cómo de ancho es el hueco dejado fuera de la barrera?", + "render": "Anchura máxima: {maxwidth:physical} m" + }, + "Overlap (cyclebarrier)": { + "question": "¿Cuánto se solapan las barreras?", + "render": "Solapado: {overlap} m" + }, + "Space between barrier (cyclebarrier)": { + "question": "¿Cuánto espacio hay entre las barreras (a lo largo de la longitud de la carretera)?", + "render": "Espacio entre barreras (a lo largo de la longitud de la carretera): {width:separation} m" + }, + "Width of opening (cyclebarrier)": { + "question": "¿Cómo de año es la apertura más pequeña al lado de las barreras?", + "render": "Anchura de la apertura: {width:opening} m" + }, + "barrier_type": { + "mappings": { + "0": { + "then": "Este es un único bolardo en la carretera" + }, + "1": { + "then": "Esta es una barrera ciclista que ralentiza a los ciclistas" + } + } } }, "title": { @@ -104,6 +209,7 @@ } }, "bench": { + "description": "Un banco es una superficie de madera, metal, piedra, ... donde un humano se puede sentar. Estas capas los visualizan y preguntan algunas preguntas sobre ellos.", "name": "Bancos", "presets": { "0": { @@ -124,6 +230,9 @@ }, "bench-colour": { "mappings": { + "0": { + "then": "Color: marrón" + }, "1": { "then": "Color: verde" }, @@ -150,7 +259,8 @@ "render": "Color: {colour}" }, "bench-direction": { - "question": "¿En qué dirección se mira al sentarse en el banco?" + "question": "¿En qué dirección se mira al sentarse en el banco?", + "render": "¿Cuando está sentado en el banco, uno mira hacia {direction}º." }, "bench-material": { "mappings": { @@ -173,11 +283,16 @@ "then": "Material: acero" } }, + "question": "¿De que está hecho el banco (asiento)?", "render": "Material: {material}" }, "bench-seats": { "question": "¿Cuántos asientos tiene este banco?", "render": "{seats} asientos" + }, + "bench-survey:date": { + "question": "¿Cuándo fue la última vez que se inspeccionó este banco?", + "render": "Este banco se inspeccionó por última vez el {survey:date}" } }, "title": { @@ -189,6 +304,11 @@ "name": "Bancos en una parada de transporte público", "tagRenderings": { "bench_at_pt-bench_type": { + "mappings": { + "2": { + "then": "No hay ningún banco aquí" + } + }, "question": "¿Qué tipo de banco es este?" }, "bench_at_pt-name": { @@ -196,21 +316,662 @@ } }, "title": { + "mappings": { + "0": { + "then": "Banco en una parada de transporte público" + } + }, "render": "Banco" } }, + "bicycle_library": { + "tagRenderings": { + "bicycle-library-target-group": { + "mappings": { + "0": { + "then": "Bicicletas para niños disponibles" + }, + "1": { + "then": "Bicicletas para adultos disponibles" + }, + "2": { + "then": "Bicicletas para discapacitados disponibles" + } + } + }, + "bicycle_library-charge": { + "render": "Alquilar una bicicleta cuesta {charge}" + } + } + }, "bicycle_rental": { + "deletion": { + "extraDeleteReasons": { + "0": { + "explanation": "{title()} ha cerrado permanentemente" + } + }, + "nonDeleteMappings": { + "0": { + "then": "Esta tienda de bicicletas alquilaba bicis, pero ya no lo hace" + } + } + }, + "description": "Estaciones de alquiler de bicicletas", + "presets": { + "0": { + "title": "una tienda de alquiler de bicicletas" + } + }, + "tagRenderings": { + "9": { + "rewrite": { + "into": { + "0": { + "1": "bicis de ciudad" + }, + "1": { + "1": "bicis eléctricas" + }, + "2": { + "1": "bicis infantiles" + }, + "3": { + "1": "bicis BMX" + }, + "4": { + "1": "bicis de montaña" + } + } + } + }, + "bicycle-types": { + "mappings": { + "0": { + "then": "Aquí se pueden alquilar bicis normales" + }, + "1": { + "then": "Aquí se pueden alquilar bicis eléctricas" + }, + "2": { + "then": "Aquí se pueden alquilar bicis BMX" + }, + "3": { + "then": "Aquí se pueden alquilar bicis de montaña" + }, + "4": { + "then": "Aquí se pueden alquilar bicis infantiles" + }, + "6": { + "then": "Aquí se pueden alquilar bicicletas de carreras" + } + }, + "question": "¿Qué tipo de bicicletas y accesorios se alquilan aquí?", + "render": "{rental} se alquilan aquí" + }, + "bicycle_rental_type": { + "mappings": { + "0": { + "then": "Esta es una tienda que se centra en el alquiler de bicicletas" + }, + "1": { + "then": "Este es un negocio de alquileres que alquila varios objetos y/o vehículos. También alquila bicicletas, pero este no es el enfoque principal" + }, + "2": { + "then": "Esta es una tienda que vende o alquila bicicletas, pero también las alquila" + }, + "3": { + "then": "Esta es una estación automática, en la que una bici se asegura mecánicamente en una estructura" + } + }, + "question": "¿Qué tipo de alquiler de bicicletas es este?" + } + }, "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, "render": "Alquiler de bicicletas" } }, + "bicycle_tube_vending_machine": { + "tagRenderings": { + "Still in use?": { + "mappings": { + "1": { + "then": "Esta máquina exprendedora está rota" + }, + "2": { + "then": "Esta máquina exprendedora está cerrada" + } + }, + "question": "¿Todavía es operacional esta máquina exprendedora?", + "render": "El estado operacional es {operational_status}" + } + } + }, "bike_cafe": { "tagRenderings": { + "bike_cafe-email": { + "question": "¿Cual es la dirección de correo electrónico de {name}?" + }, + "bike_cafe-phone": { + "question": "¿Cual es el número de teléfono de {name}?" + }, "bike_cafe-repair-tools": { "question": "¿Hay herramientas para reparar su propia bicicleta?" } } }, + "bike_cleaning": { + "description": "Una capa que muestra facilidades en las que uno puede limpiar su bici", + "name": "Servicio de limpieza de bicis", + "presets": { + "0": { + "title": "un servicio de limpieza de bicis" + } + }, + "tagRenderings": { + "bike_cleaning-charge": { + "mappings": { + "0": { + "then": "Un servicio de limpieza gratis" + }, + "1": { + "then": "Gratis" + }, + "2": { + "then": "El servicio de limpieza tiene una tarifa" + } + }, + "question": "¿Cuánto cuesta utilizar el servicio de limpieza?", + "render": "Utilizar el servicio de limpieza cuesta {charge}" + }, + "bike_cleaning-service:bicycle:cleaning:charge": { + "mappings": { + "0": { + "then": "El servicio de limpieza es gratis" + }, + "1": { + "then": "Gratis" + }, + "2": { + "then": "El servicio de limpieza tiene una tasa, pero la cantidad se desconoce" + } + }, + "question": "¿Cuánto cuesta utilizar el servicio de limpieza?", + "render": "Utilizar el servicio de limpieza cuesta {service:bicycle:cleaning:charge}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Servicio de limpieza de bicis {name}" + } + }, + "render": "Servicio de limpieza de bicis" + } + }, + "bike_parking": { + "description": "Una capa que muestra donde puedes aparcar tu bici", + "name": "Aparcamiento de bicis", + "presets": { + "0": { + "title": "un aparcamiento de bicis" + } + }, + "tagRenderings": { + "Access": { + "mappings": { + "0": { + "then": "Accesible públicamente" + }, + "1": { + "then": "El acceso es primariamente para visitantes a un negocio" + }, + "2": { + "then": "El acceso se limita a miembros de una escuela, compañía u organización" + } + }, + "question": "¿Quién puede utilizar este aparcamiento de bicicletas?", + "render": "{access}" + }, + "Bicycle parking type": { + "mappings": { + "5": { + "then": "Caseta" + }, + "6": { + "then": "Bolardo" + }, + "7": { + "then": "Una área en el suelo que está marcada para el aparcamiento de bicicletas" + } + }, + "question": "¿Cual es el tipo de este aparcamiento de bicicletas?", + "render": "Este es un aparcamiento de bicicletas del tipo: {bicycle_parking}" + }, + "Capacity": { + "question": "¿Cuántas bicicletas caben en este aparcamiento de bicicletas (incluyendo posibles bicicletas de carga)?", + "render": "Espacio para {capacity} bicis" + }, + "Cargo bike capacity?": { + "question": "¿Cuántas bicicletas de carga caben en este aparcamiento de bicicletas?", + "render": "En este aparcamiento caben {capacity:cargo_bike} bicis de carga" + }, + "Cargo bike spaces?": { + "mappings": { + "0": { + "then": "Este aparcamiento tiene espacio para bicicletas de carga" + }, + "1": { + "then": "Este aparcamiento tiene huecos (oficialmente) designados para bicicletas de carga." + }, + "2": { + "then": "No se permite aparcar bicicletas de carga" + } + }, + "question": "¿Este aparcamiento de bicicletas tiene huevos para bicicletas de carga?" + }, + "Is covered?": { + "mappings": { + "0": { + "then": "Este aparcamiento está cubierto (tiene un tejado)" + }, + "1": { + "then": "Este aparcamiento no está cubierto" + } + }, + "question": "¿Está cubierto este aparcamiento? Selecciona \"cubierto\" también para aparcamientos interiores." + }, + "Underground?": { + "mappings": { + "0": { + "then": "Aparcamiento subterráneo" + }, + "1": { + "then": "Aparcamiento a nivel de calle" + }, + "2": { + "then": "Aparcamiento de azotea" + } + }, + "question": "¿Cual es la localización relativa de este aparcamiento de bicicletas?" + } + }, + "title": { + "render": "Aparcamiento de bicis" + } + }, + "bike_repair_station": { + "description": "Una capa que muestra bombas de bicicletas y puestos de herramientas de reparación de bicicletas", + "name": "Bomba y reparación de bicicletas", + "presets": { + "0": { + "description": "Un dispositivo para inflar tus ruedas en una posición fija en el espacio público.", + "title": "una bomba de bicicletas" + }, + "1": { + "description": "Una bomba de bicicletas y herramientas para reparar tu bicicleta en el espacio público. Las herramientas habitualmente están aseguradas con cadenas contra el robo.", + "title": "En estación de reparación de bicicletas y bomba" + }, + "2": { + "description": "Herramientas para reparar tu bici en el espacio público (sin bomba).Las herramientas están aseguradas contra el robo.", + "title": "una estación de reparación de bicicletas sin bomba" + } + }, + "tagRenderings": { + "Operational status": { + "mappings": { + "0": { + "then": "La bomba de bicicletas está rota" + }, + "1": { + "then": "La bomba de bicicletas está operativa" + } + }, + "question": "¿Todavía está operativa la bomba de bicicletas?" + }, + "access": { + "mappings": { + "0": { + "then": "Accesible públicamente" + }, + "1": { + "then": "Accesible públicamente" + }, + "2": { + "then": "Solo para clientes" + }, + "3": { + "then": "No accesible para el público general" + }, + "4": { + "then": "No accesible para el público general" + } + }, + "question": "¿A quién se le permite utilizar esta estación de reparación?" + }, + "bike_repair_station-available-services": { + "mappings": { + "0": { + "then": "Solo hay una bomba presente" + }, + "1": { + "then": "Solo hay herramientas (destornilladores, pinzas...) presentes" + }, + "2": { + "then": "Hay tanto herramientas como bombas" + } + }, + "question": "¿Qué servicios están disponibles en esta localización?" + }, + "bike_repair_station-bike-chain-tool": { + "mappings": { + "0": { + "then": "Hay una herramienta de cadenas" + }, + "1": { + "then": "No hay herramienta de cadenas" + } + }, + "question": "¿Esta estación de reparación tiene una herramienta especial para reparar la cadena de tu bici?" + }, + "bike_repair_station-bike-stand": { + "mappings": { + "0": { + "then": "Hay un gancho o soporte" + }, + "1": { + "then": "No hay ningún gancho o soporte" + } + }, + "question": "¿Esta estación tiene un gancho para colgar tu bici o un soporte para elevarla?" + }, + "bike_repair_station-electrical_pump": { + "mappings": { + "0": { + "then": "Bomba manual" + }, + "1": { + "then": "Bomba eléctrica" + } + }, + "question": "¿Hay una bomba eléctrica para bicis?" + }, + "bike_repair_station-email": { + "question": "¿Es esta la dirección de correo electrónico del mantenedor?" + }, + "bike_repair_station-manometer": { + "mappings": { + "0": { + "then": "Hay un manómetro" + }, + "1": { + "then": "No hay ningún manometro" + }, + "2": { + "then": "Hay un manómetro pero está roto" + } + }, + "question": "¿La bomba tiene un indicador de presión o manómetro?" + }, + "bike_repair_station-opening_hours": { + "mappings": { + "0": { + "then": "Siempre abierto" + } + }, + "question": "¿Cuándo está abierto este punto de reparación de bicicletas?" + }, + "bike_repair_station-operator": { + "question": "¿Quién mantiene esta bomba para bicicletas?", + "render": "Mantenido por {operator}" + }, + "bike_repair_station-phone": { + "question": "¿Cual es el número de teléfono del mantenedor?" + }, + "bike_repair_station-valves": { + "question": "¿Que válvulas se soportan?", + "render": "Esta bomba soporta las siguiente válvulas: {valves}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Estación de reparación de bicis" + }, + "1": { + "then": "Estación de reparación de bicis" + }, + "2": { + "then": "Bomba rota" + }, + "3": { + "then": "Bomba de bicicletas {name}" + }, + "4": { + "then": "Bomba para bicicletas" + } + }, + "render": "Estación de bicis (bomba y reparación)" + } + }, + "bike_shop": { + "description": "Una tiene que vende específicamente bicis u objetos relacionados", + "tagRenderings": { + "bike_repair_bike-pump-service": { + "mappings": { + "0": { + "then": "Esta tienda ofrece una bomba para cualquiera" + }, + "1": { + "then": "Esta tienda no ofrece una bomba para cualquiera" + }, + "2": { + "then": "Hay una bomba para bicicletas, se muestra como un punto separado " + } + }, + "question": "¿Esta tienda ofrece una bomba para que la utilice cualquiera?" + }, + "bike_repair_bike-wash": { + "mappings": { + "0": { + "then": "Esta tienda limpia bicicletas" + }, + "1": { + "then": "Esta tienda tiene una instalación donde uno puede limpiar bicicletas por si mismo" + }, + "2": { + "then": "Esta tienda no ofrece limpieza de bicicletas" + } + }, + "question": "¿Aquí se lavan bicicletas?" + }, + "bike_repair_rents-bikes": { + "mappings": { + "0": { + "then": "Esta tienda alquila bicis" + }, + "1": { + "then": "Esta tienda no alquila bicis" + } + }, + "question": "¿Alquila bicicis esta tienda?" + }, + "bike_repair_repairs-bikes": { + "mappings": { + "0": { + "then": "Esta tienda repara bicis" + }, + "1": { + "then": "Esta tienda no repara bicis" + }, + "2": { + "then": "Esta tienda solo repara bicis compradas aquí" + }, + "3": { + "then": "Esta tienda solo repara bicis de una cierta marca" + } + }, + "question": "¿Repara bicis esta tienda?" + }, + "bike_repair_second-hand-bikes": { + "mappings": { + "0": { + "then": "Esta tienda vende bicis de segunda mano" + }, + "1": { + "then": "Esta tienda no vende bicis de segunda mano" + }, + "2": { + "then": "Esta tienda solo vende bicis de segunda mano" + } + }, + "question": "¿Vende bicis de segunda mano esta tienda?" + }, + "bike_repair_sells-bikes": { + "mappings": { + "0": { + "then": "Esta tienda vende bicis" + }, + "1": { + "then": "Esta tienda no vende bicis" + } + }, + "question": "¿Vende bicis esta tienda?" + }, + "bike_repair_tools-service": { + "question": "¿Hay herramientas para reparar tu propia bici?" + }, + "bike_shop-access": { + "render": "Solo accesible a {access}" + }, + "bike_shop-email": { + "question": "¿Cual es la dirección de correo electrónico de {name}?" + }, + "bike_shop-is-bicycle_shop": { + "render": "Esta tienda está especializada en vender {shop} y hace actividades relacionadas con bicicletas" + }, + "bike_shop-name": { + "question": "¿Cual es el nombre de esta tienda de bicicletas?", + "render": "Esta tienda de bicicletas se llama {name}" + }, + "bike_shop-phone": { + "question": "¿Cual es el número de teléfono de {name}?" + }, + "bike_shop-website": { + "question": "¿Cual es el sitio web de {name}?" + } + }, + "title": { + "mappings": { + "2": { + "then": "Alquiler de bicicletas {name}" + }, + "3": { + "then": "Reparación de bicis {name}" + }, + "4": { + "then": "Tienda de bicis {name}" + } + } + } + }, + "bike_themed_object": { + "description": "Una capa con los objetos relacionados con bicis pero que no coinciden con ninguna otra capa", + "name": "Objeto relacionada con bicis", + "title": { + "mappings": { + "1": { + "then": "Carril bici" + } + }, + "render": "Objeto relacionado con bicis" + } + }, + "binocular": { + "tagRenderings": { + "binocular-charge": { + "question": "¿Cuánto hay que pagar para utilizar estos binoculares?", + "render": "Utilizar estos binoculares cuesta {charge}" + }, + "binocular-direction": { + "question": "¿Cuándo uno mira a través de este binocular, en qué dirección lo hace?", + "render": "Mira hacia {direction}º" + } + }, + "title": { + "render": "Binoculares" + } + }, + "birdhide": { + "filter": { + "0": { + "options": { + "0": { + "question": "Accesible con sillas de ruedas" + } + } + } + }, + "name": "Lugares para ver pájaros", + "presets": { + "0": { + "description": "Un refugio cubierto donde se pueden ver pájaros confortablemente" + }, + "1": { + "description": "Una pantalla o pared con aperturas para ver pájaros" + } + }, + "tagRenderings": { + "bird-hide-wheelchair": { + "mappings": { + "0": { + "then": "Hay provisiones especiales para usuarios de sillas de ruedas" + }, + "3": { + "then": "No accesible a usuarios con sillas de ruedas" + } + } + }, + "birdhide-operator": { + "mappings": { + "0": { + "then": "Operado por Natuurpunt" + } + }, + "render": "Operado por {operator}" + } + } + }, + "cafe_pub": { + "deletion": { + "extraDeleteReasons": { + "0": { + "explanation": "{title()} ha cerrado permanentemente" + } + } + }, + "description": "Una capa que muestra cafeterías y bares donde uno se puede reunir con una bebida. La capa pregunta algunas preguntas relevantes", + "filter": { + "0": { + "options": { + "0": { + "question": "Abiert oahora" + } + } + } + }, + "name": "Cafeterías y bares", + "presets": { + "0": { + "description": "Un bar, principalmente para beber cervezas en un interior templado y relajado" + } + } + }, "charging_station": { "tagRenderings": { "Authentication": { @@ -332,5 +1093,125 @@ "question": "¿Se puede visitar esta torre?" } } + }, + "tree_node": { + "description": "Una capa que muestra árboles", + "name": "Árbol", + "presets": { + "0": { + "description": "Un árbol de hojas como el Roble o el Álamo.", + "title": "árbol de hoja ancha" + }, + "1": { + "description": "Un árbol de hojas agujas, como el Pino o el Abeto.", + "title": "Árbol tipo Conífera" + }, + "2": { + "description": "Si no estás seguro de si es un árbol de hoja ancha o de hoja de aguja.", + "title": "un árbol" + } + }, + "tagRenderings": { + "tree-decidouous": { + "mappings": { + "0": { + "then": "Caduco o Deciduo: el árbol pierde las hojas en un período del año" + }, + "1": { + "then": "Siempreverde." + } + }, + "question": "¿El árbol es Siempreverde o Caduco?" + }, + "tree-denotation": { + "mappings": { + "0": { + "then": "El árbol es notable debido a su tamaño o ubicación prominente. Es útil para la navegación." + }, + "1": { + "then": "El árbol es un monumento natural, por ejemplo, porque es especialmente antiguo, o de una especie valiosa." + }, + "2": { + "then": "El árbol se utiliza con fines agrícolas, por ejemplo, en un huerto." + }, + "3": { + "then": "El árbol está en un parque o similar (cementerio, recinto escolar, ...)." + }, + "4": { + "then": "El árbol está en un jardín privado o residencial." + }, + "5": { + "then": "El árbol está en bandejón de una avenida." + }, + "6": { + "then": "El árbol está en un zona urbana." + }, + "7": { + "then": "El árbol está fuera de una zona urbana." + } + }, + "question": "¿Qué importancia tiene este árbol? Elige la primera respuesta que corresponda." + }, + "tree-height": { + "mappings": { + "0": { + "then": "Altura: {height} m" + } + }, + "render": "Altura: {height}" + }, + "tree-heritage": { + "mappings": { + "0": { + "then": "Registrado como patrimonio por Onroerend Erfgoed Flandes" + }, + "1": { + "then": "Registrado como patrimonio por la Dirección de Patrimonio Cultural de Bruselas" + }, + "2": { + "then": "Registrado como patrimonio por una organización diferente" + }, + "3": { + "then": "No registrado como patrimonio" + }, + "4": { + "then": "Registrado como patrimonio por un organización diferente" + } + }, + "question": "¿Este árbol es patrimonio registrado?" + }, + "tree-leaf_type": { + "mappings": { + "0": { + "then": "Latifoliada" + }, + "1": { + "then": "Hoja aguja" + }, + "2": { + "then": "Permanentemente sin hojas" + } + }, + "question": "¿Es un árbol de hoja ancha o de hoja aguja?" + }, + "tree_node-name": { + "mappings": { + "0": { + "then": "No identificas la especie." + } + }, + "question": "El árbol no tiene nombre?." + }, + "tree_node-ref:OnroerendErfgoed": { + "question": "¿Cuál es la identificación emitida por Onroerend Erfgoed Flandes?" + }, + "tree_node-wikidata": { + "question": "¿Cuál es el ID de Wikidata para este árbol?", + "render": "\"\"/ Wikidata: {wikidata}" + } + }, + "title": { + "render": "Árbol" + } } } \ No newline at end of file diff --git a/langs/layers/fr.json b/langs/layers/fr.json index 301a25812..702021fff 100644 --- a/langs/layers/fr.json +++ b/langs/layers/fr.json @@ -1035,6 +1035,194 @@ } } }, + "climbing": { + "description": "Opportunité d’escalade", + "name": "Opportunité d’escalade", + "presets": { + "0": { + "description": "Opportunité d’escalade", + "title": "une opportunité d’escalade" + } + }, + "tagRenderings": { + "Contained routes hist": { + "render": "

    Résumé des difficultés

    {histogram(_difficulty_hist)}" + }, + "Contained routes length hist": { + "render": "

    Résumé de longueur

    {histogram(_length_hist)}" + }, + "Contained_climbing_routes": { + "render": "

    Contient {_contained_climbing_routes_count} voies

      {_contained_climbing_routes}
    " + }, + "Rock type (crag/rock/cliff only)": { + "mappings": { + "0": { + "then": "Calcaire" + } + }, + "question": "Quel est le type de roche ?", + "render": "La roche est du {rock}" + }, + "Type": { + "mappings": { + "0": { + "then": "Rocher d’escalade, rocher avec une ou peu de voie permettant d’escalader sans corde" + }, + "1": { + "then": "Mur d’escalade, rocher avec plusieurs voies d’escalades" + } + } + }, + "name": { + "mappings": { + "0": { + "then": "Ce site n’a pas de nom" + } + }, + "question": "Quel est le nom de ce site ?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Mur d’escalade {name}" + }, + "1": { + "then": "Zone d’escalade {name}" + }, + "2": { + "then": "Site d’escalade" + }, + "3": { + "then": "Opportunité d’escalade {name}" + } + }, + "render": "Opportunité d’escalade" + } + }, + "climbing_club": { + "description": "Club ou association d’escalade", + "name": "Club d’escalade", + "presets": { + "0": { + "description": "Un club d’escalade", + "title": "une club d’escalade" + }, + "1": { + "description": "Une association d’escalade", + "title": "une association d’escalade" + } + }, + "tagRenderings": { + "climbing_club-name": { + "question": "Quel est le nom du club ou de l’association ?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Association d’escalade" + } + }, + "render": "Club d’escalade" + } + }, + "climbing_gym": { + "description": "Une salle d’escalade", + "name": "Salle d’escalade", + "tagRenderings": { + "name": { + "question": "Quel est le nom de la salle d’escalade ?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Salle d’escalade {name}" + } + }, + "render": "Salle d’escalade" + } + }, + "climbing_opportunity": { + "description": "Opportunité d’escalade ?", + "name": "Opportunités d’escalade ?", + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + }, + "climbing-possible": { + "mappings": { + "0": { + "then": "Escalader est possible" + }, + "1": { + "then": "Escalader n’est pas possible" + }, + "2": { + "then": "Escalader n’est pas possible" + } + }, + "question": "Est-il possible d’escalader ici ?" + } + }, + "title": { + "render": "Opportunité d’escalade ?" + } + }, + "climbing_route": { + "name": "Voies d’escalade", + "presets": { + "0": { + "title": "une voie d’escalade" + } + }, + "tagRenderings": { + "Bolts": { + "mappings": { + "0": { + "then": "Cette voie n’a pas de prises" + }, + "1": { + "then": "Cette voie n’a pas de prises" + } + }, + "question": "Combien de prises cette voie possède avant d’atteindre la moulinette ?", + "render": "Cette voie a {climbing:bolts} prises" + }, + "Difficulty": { + "question": "Quelle est la difficulté de cette voie selon le système franco-belge ?", + "render": "Selon le système franco-belge, la difficulté de cette voie est de {climbing:grade:french}" + }, + "Length": { + "question": "Quelle est la longueur de cette voie (en mètres) ?", + "render": "Cette voie fait {canonical(climbing:length)} de long" + }, + "Name": { + "mappings": { + "0": { + "then": "Cette voie n’a pas de nom" + } + }, + "question": "Quel est le nom de cette voie d’escalade ?", + "render": "{name}" + }, + "Rock type": { + "render": "Le type de roche est {_embedding_features_with_rock:rock} selon le mur" + } + }, + "title": { + "mappings": { + "0": { + "then": "Voie d’escalade {name}" + } + }, + "render": "Voie d’escalade" + } + }, "crossings": { "description": "Traversée pour piétons et cyclistes", "name": "Traversée", @@ -2418,5 +2606,68 @@ }, "watermill": { "name": "Moulin à eau" + }, + "windturbine": { + "name": "Éolienne", + "presets": { + "0": { + "title": "une éolienne" + } + }, + "tagRenderings": { + "turbine-diameter": { + "question": "Quel est le diamètre du rotor en mètres ?", + "render": "Le diamètre du rotor est de {rotor:diameter} mètres." + }, + "turbine-height": { + "question": "Quelle est la hauteur totale de l’éolienne en mètres, pales incluses ?", + "render": "La hauteur totale, incluant les pales, est de {height} mètres." + }, + "turbine-operator": { + "question": "Qui est l’exploitant de cette éolienne ?", + "render": "Cette éolienne est opérée par {operator}." + }, + "turbine-output": { + "question": "Quel est la puissance générée par cette éolienne ?", + "render": "La puissance générée par cette éolienne est de {generator:output:electricity}." + }, + "turbine-start-date": { + "question": "Depuis quand l’éolienne est-elle en fonctionnement ?", + "render": "L’éolienne est active depuis {start_date}." + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "éolienne" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " megawatts" + }, + "1": { + "human": " kilowatts" + }, + "2": { + "human": " watts" + }, + "3": { + "human": " gigawatts" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " mètres" + } + } + } + } } -} +} \ No newline at end of file diff --git a/langs/layers/gl.json b/langs/layers/gl.json index aa2aa6ff9..70689c459 100644 --- a/langs/layers/gl.json +++ b/langs/layers/gl.json @@ -405,4 +405,4 @@ "render": "Bicicleta pantasma" } } -} +} \ No newline at end of file diff --git a/langs/layers/hu.json b/langs/layers/hu.json index 4ca5c93e3..5bed8bef6 100644 --- a/langs/layers/hu.json +++ b/langs/layers/hu.json @@ -474,6 +474,33 @@ } } }, + "climbing_club": { + "description": "Mászóegyesület vagy -szervezet", + "name": "Mászóegyesület", + "presets": { + "0": { + "description": "Egy mászóegyesület", + "title": "Mászóegyesület" + }, + "1": { + "description": "Mászással foglalkozó civil szervezet", + "title": "Mászószervezet" + } + }, + "tagRenderings": { + "climbing_club-name": { + "question": "Mi a neve ennek a mászóegyesületnek vagy szervezetnek?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Mászószervezet" + } + } + } + }, "drinking_water": { "description": "Ivóvizet adó kutakat megjelenítő réteg", "name": "Ivóvíz", @@ -528,6 +555,41 @@ "render": "Emlékkerékpár" } }, + "hackerspace": { + "description": "Hackerspace", + "name": "Hackerspace", + "presets": { + "0": { + "description": "A hackerspace egy olyan hely, ahol szoftverek iránt érdeklő emberek találkoznak", + "title": "Hackerspace" + }, + "1": { + "description": "A makerspace olyan hely, ahol a barkácsolás szerelmesei találkoznak, hogy olyan elektronikai eszközökkel kísérletezzenek, mint például az Arduino vagy a LEDstrips.", + "title": "Makerspace" + } + }, + "tagRenderings": { + "is_makerspace": { + "mappings": { + "0": { + "then": "Ez egy makerspace" + }, + "1": { + "then": "Ez egy hagyományos (szoftverekkel foglalkozó) hackerspace" + } + }, + "question": "Ez hackerspace vagy makerspace?" + } + }, + "title": { + "mappings": { + "0": { + "then": " {name}" + } + }, + "render": "Hackerspace" + } + }, "public_bookcase": { "description": "Egy utcai szekrény könyvekkel, amelyet bárki használhat", "filter": { @@ -651,5 +713,63 @@ } } } + }, + "windturbine": { + "name": "Szélerőmű", + "presets": { + "0": { + "title": "Szélerőmű" + } + }, + "tagRenderings": { + "turbine-diameter": { + "question": "Hány méter a rotorátmérője ennek a szélturbinának?", + "render": "A szélturbina rotorátmérője: {rotor:diameter} méter." + }, + "turbine-height": { + "question": "Hány méter a szélerőmű teljes magassága (a rotor sugarával együtt)?", + "render": "A szélerőmű teljes (rotor sugarával együtt számított) magassága: {height} méter." + }, + "turbine-operator": { + "question": "Ki üzemelteti ezt a szélturbinát?", + "render": "Ennek a szélerőműnek az üzemeltetője: {operator}." + }, + "turbine-output": { + "question": "Mekkora a teljesítménye ennek a szélturbinának? (pl. 2.3 MW)", + "render": "A szélerőmű teljesítménye: {generator:output:electricity}." + }, + "turbine-start-date": { + "question": "Mikor helyezték üzembe ezt a szélerőművet?", + "render": "A szélerőmű üzembe helyezése: {start_date}." + } + }, + "title": { + "render": "szélerőmű" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " megawatt" + }, + "1": { + "human": " kilowatt" + }, + "2": { + "human": " watt" + }, + "3": { + "human": " gigawatt" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " méter" + } + } + } + } } } \ No newline at end of file diff --git a/langs/layers/id.json b/langs/layers/id.json index 70a2e3f55..12c017556 100644 --- a/langs/layers/id.json +++ b/langs/layers/id.json @@ -151,6 +151,41 @@ } } }, + "climbing": { + "tagRenderings": { + "name": { + "render": "{name}" + } + } + }, + "climbing_club": { + "tagRenderings": { + "climbing_club-name": { + "render": "{name}" + } + } + }, + "climbing_gym": { + "tagRenderings": { + "name": { + "render": "{name}" + } + } + }, + "climbing_opportunity": { + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + } + } + }, + "climbing_route": { + "tagRenderings": { + "Name": { + "render": "{name}" + } + } + }, "cycleways_and_roads": { "tagRenderings": { "Maxspeed (for road)": { @@ -395,5 +430,53 @@ }, "watermill": { "name": "Kincir Air" + }, + "windturbine": { + "tagRenderings": { + "turbine-operator": { + "render": "Turbin angin ini dioperasikan oleh {operator}." + }, + "turbine-output": { + "question": "Berapa output daya dari turbin angin ini? (misalnya 2,3 MW)", + "render": "Output daya dari turbin angin ini adalah {generator:output:electricity}." + }, + "turbine-start-date": { + "question": "Kapan turbin angin ini mulai beroperasi?", + "render": "Turbin angin ini mulai beroperasi pada/dalam {start_date}." + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "turbin angin" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " megawat" + }, + "1": { + "human": " kilowat" + }, + "2": { + "human": " watt" + }, + "3": { + "human": " gigawatt" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " meter" + } + } + } + } } } \ No newline at end of file diff --git a/langs/layers/it.json b/langs/layers/it.json index 333ed0f47..859806f3a 100644 --- a/langs/layers/it.json +++ b/langs/layers/it.json @@ -791,6 +791,194 @@ "render": "Oggetto relativo alle bici" } }, + "climbing": { + "description": "Un’opportunità di arrampicata", + "name": "Opportunità di arrampicata", + "presets": { + "0": { + "description": "Un’opportunità di arrampicata", + "title": "una opportunità di arrampicata" + } + }, + "tagRenderings": { + "Contained routes hist": { + "render": "

    Riassunto delle difficoltà

    {histogram(_difficulty_hist)}" + }, + "Contained routes length hist": { + "render": "

    Riassunto della lunghezza

    {histogram(_length_hist)}" + }, + "Contained_climbing_routes": { + "render": "

    Contiene {_contained_climbing_routes_count} vie

      {_contained_climbing_routes}
    " + }, + "Rock type (crag/rock/cliff only)": { + "mappings": { + "0": { + "then": "Calcare" + } + }, + "question": "Qual è il tipo di roccia qua?", + "render": "Il tipo di roccia è {rock}" + }, + "Type": { + "mappings": { + "0": { + "then": "Un masso per arrampicata (una singola roccia o falesia con una o poche vie di arrampicata che possono essere scalate in sicurezza senza una corda)" + }, + "1": { + "then": "Un muro da arrampicata (un singolo masso o falesia con almeno qualche via per arrampicata)" + } + } + }, + "name": { + "mappings": { + "0": { + "then": "Questa opportunità di arrampicata non ha un nome" + } + }, + "question": "Qual è il nome di questa opportunità di arrampicata?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Muro da arrampicata {name}" + }, + "1": { + "then": "Area di arrampicata {name}" + }, + "2": { + "then": "Sito di arrampicata" + }, + "3": { + "then": "Opportunità di arrampicata {name}" + } + }, + "render": "Opportunità di arrampicata" + } + }, + "climbing_club": { + "description": "Un club o associazione di arrampacata", + "name": "Club di arrampicata", + "presets": { + "0": { + "description": "Un club di arrampicata", + "title": "una club di arrampicata" + }, + "1": { + "description": "Un’associazione che ha a che fare con l’arrampicata", + "title": "una associazione di arrampicata" + } + }, + "tagRenderings": { + "climbing_club-name": { + "question": "Qual è il nome di questo club o associazione di arrampicata?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Associazione di arrampicata" + } + }, + "render": "Club di arrampicata" + } + }, + "climbing_gym": { + "description": "Una palestra di arrampicata", + "name": "Palestre di arrampicata", + "tagRenderings": { + "name": { + "question": "Qual è il nome di questa palestra di arrampicata?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Palestra di arrampicata {name}" + } + }, + "render": "Palestra di arrampicata" + } + }, + "climbing_opportunity": { + "description": "Un’opportunità di arrampicata?", + "name": "Opportunità di arrampicata?", + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + }, + "climbing-possible": { + "mappings": { + "0": { + "then": "È possibile arrampicarsi qua" + }, + "1": { + "then": "Non è possibile arrampicarsi qua" + }, + "2": { + "then": "Non è possibile arrampicarsi qua" + } + }, + "question": "È possibile arrampicarsi qua?" + } + }, + "title": { + "render": "Opportunità di arrampicata?" + } + }, + "climbing_route": { + "name": "Vie di arrampicata", + "presets": { + "0": { + "title": "una via di arrampicata" + } + }, + "tagRenderings": { + "Bolts": { + "mappings": { + "0": { + "then": "In questo percorso non sono presenti bulloni" + }, + "1": { + "then": "In questo percorso non sono presenti bulloni" + } + }, + "question": "Quanti bulloni sono presenti in questo percorso prima di arrivare alla moulinette?", + "render": "Questo percorso ha {climbing:bolts} bulloni" + }, + "Difficulty": { + "question": "Qual è la difficoltà di questa via di arrampicata nel sistema francese/belga?", + "render": "Il grado di difficoltà è {climbing:grade:french} nel sistema francese/belga" + }, + "Length": { + "question": "Quanto è lunga questa via di arrampicata (in metri)?", + "render": "Questo percorso è lungo {canonical(climbing:length)}" + }, + "Name": { + "mappings": { + "0": { + "then": "Questa via di arrampicata non ha un nome" + } + }, + "question": "Come si chiama questa via di arrampicata?", + "render": "{name}" + }, + "Rock type": { + "render": "Il tipo di roccia è {_embedding_features_with_rock:rock} come dichiarato sul muro circostante" + } + }, + "title": { + "mappings": { + "0": { + "then": "Via di arrampicata {name}" + } + }, + "render": "Via di arrampicata" + } + }, "defibrillator": { "name": "Defibrillatori", "presets": { @@ -1992,5 +2180,68 @@ "title": { "render": "Punto panoramico" } + }, + "windturbine": { + "name": "pala eolica", + "presets": { + "0": { + "title": "una pala eolica" + } + }, + "tagRenderings": { + "turbine-diameter": { + "question": "Qual è il diametro (in metri) del rotore di questa pala eolica?", + "render": "Il diametro del rotore di questa pala eolica è di {rotor:diameter} metri." + }, + "turbine-height": { + "question": "Qual è l’altezza (in metri e raggio del rotore incluso) di questa pala eolica?", + "render": "L’altezza totale (raggio del rotore incluso) di questa pala eolica è di {height} metri." + }, + "turbine-operator": { + "question": "Chi gestisce questa pala eolica?", + "render": "Questa pala eolica è gestita da {operator}." + }, + "turbine-output": { + "question": "Quant’è la potenza generata da questa pala eolica? (ad es. 2.3 MW)", + "render": "La potenza generata da questa pala eolica è {generator:output:electricity}." + }, + "turbine-start-date": { + "question": "Quando è entrata in funzione questa pala eolica?", + "render": "Questa pala eolica è entrata in funzione in data {start_date}." + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "pala eolica" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " megawatt" + }, + "1": { + "human": " kilowatt" + }, + "2": { + "human": " watt" + }, + "3": { + "human": " gigawatt" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " metri" + } + } + } + } } } \ No newline at end of file diff --git a/langs/layers/ja.json b/langs/layers/ja.json index a81b39656..b8075b171 100644 --- a/langs/layers/ja.json +++ b/langs/layers/ja.json @@ -121,6 +121,130 @@ "render": "アートワーク" } }, + "climbing": { + "description": "登坂教室", + "name": "登坂教室", + "presets": { + "0": { + "description": "登坂教室", + "title": "登坂教室" + } + }, + "tagRenderings": { + "name": { + "mappings": { + "0": { + "then": "この登坂教室には名前がついていない" + } + }, + "question": "この登坂教室の名前は何ですか?", + "render": "{name}" + } + }, + "title": { + "render": "登坂教室" + } + }, + "climbing_club": { + "description": "クライミングクラブや団体", + "name": "クライミングクラブ", + "presets": { + "0": { + "description": "クライミングクラブ", + "title": "クライミングクラブ" + }, + "1": { + "description": "登山に関わるNGO", + "title": "クライミングNGO" + } + }, + "tagRenderings": { + "climbing_club-name": { + "question": "この登山クラブやNGOの名前は何ですか?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "クライミングNGO" + } + }, + "render": "クライミングクラブ" + } + }, + "climbing_gym": { + "description": "クライミングジム", + "name": "クライミングジム", + "tagRenderings": { + "name": { + "question": "このクライミングジムは何という名前ですか?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "クライミングジム{name}" + } + }, + "render": "クライミングジム" + } + }, + "climbing_opportunity": { + "description": "登坂教室?", + "name": "登坂教室?", + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + }, + "climbing-possible": { + "mappings": { + "0": { + "then": "ここでは登ることができる" + }, + "1": { + "then": "ここでは登ることができない" + }, + "2": { + "then": "ここでは登ることができない" + } + }, + "question": "ここで登坂はできますか?" + } + }, + "title": { + "render": "登坂教室?" + } + }, + "climbing_route": { + "name": "登坂ルート", + "tagRenderings": { + "Difficulty": { + "render": "フランス/ベルギーのランク評価システムによると、{climbing:grade:french}の困難度です" + }, + "Length": { + "render": "このルート長は、 {canonical(climbing:length)} メーターです" + }, + "Name": { + "mappings": { + "0": { + "then": "この登坂ルートには名前がありません" + } + }, + "question": "この登坂ルートの名前は何ですか?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "登坂ルート{name}" + } + }, + "render": "登坂ルート" + } + }, "extinguisher": { "description": "消火栓を表示するマップレイヤ。", "name": "消火器の地図です。", diff --git a/langs/layers/nb_NO.json b/langs/layers/nb_NO.json index 41892f31d..487780cc5 100644 --- a/langs/layers/nb_NO.json +++ b/langs/layers/nb_NO.json @@ -1,4 +1,25 @@ { + "address": { + "description": "Adresser", + "name": "Kjente adresser i OSM", + "title": { + "render": "Kjent adresse" + } + }, + "ambulancestation": { + "presets": { + "0": { + "description": "Legg til en ambulansestasjon på kartet", + "title": "en ambulansestasjon" + } + }, + "tagRenderings": { + "ambulance-name": { + "question": "Hva er navnet på denne ambulansestasjonen?", + "render": "Denne stasjonen heter {name}." + } + } + }, "artwork": { "name": "Kunstverk", "presets": { @@ -174,6 +195,75 @@ } } }, + "climbing": { + "description": "En klatremulighet", + "presets": { + "0": { + "description": "En klatremulighet", + "title": "en klatremulighet" + } + }, + "title": { + "render": "Klatremulighet" + } + }, + "climbing_club": { + "description": "En klatreklubb eller organisasjoner", + "name": "Klatreklubb", + "presets": { + "0": { + "description": "En klatreklubb", + "title": "en klatreklubb" + } + }, + "title": { + "render": "Klatreklubb" + } + }, + "climbing_opportunity": { + "description": "En klatremulighet?", + "name": "Klatremuligheter?", + "tagRenderings": { + "climbing-possible": { + "mappings": { + "0": { + "then": "Klatring er mulig her" + }, + "1": { + "then": "Klatring er ikke mulig her" + }, + "2": { + "then": "Klatring er ikke mulig her" + } + }, + "question": "Er klatring mulig her?" + } + }, + "title": { + "render": "Klatremulighet?" + } + }, + "climbing_route": { + "name": "Klatreruter", + "tagRenderings": { + "Length": { + "question": "Hvor mange meter er klatreruten?", + "render": "Denne ruten er {canonical(climbing:length)} lang" + }, + "Name": { + "mappings": { + "0": { + "then": "Denne klatreruten har ikke noe navn" + } + }, + "question": "Hva er navnet på denne klatreruten?", + "render": "{name}" + } + }, + "title": { + "render": "Klatrerute" + } + }, "extinguisher": { "description": "Kartlag for å vise brannslokkere.", "name": "Kart over brannhydranter", @@ -248,5 +338,16 @@ } } } + }, + "windturbine": { + "units": { + "0": { + "applicableUnits": { + "1": { + "human": " kilowatt" + } + } + } + } } } \ No newline at end of file diff --git a/langs/layers/nl.json b/langs/layers/nl.json index da631ed32..fd581e459 100644 --- a/langs/layers/nl.json +++ b/langs/layers/nl.json @@ -2311,6 +2311,154 @@ } } }, + "climbing": { + "description": "Een klimgelegenheid", + "name": "Klimgelegenheden", + "presets": { + "0": { + "description": "Een klimgelegenheid", + "title": "een klimgelegenheid" + } + }, + "tagRenderings": { + "Rock type (crag/rock/cliff only)": { + "mappings": { + "0": { + "then": "Kalksteen" + } + } + }, + "name": { + "mappings": { + "0": { + "then": "Dit Klimgelegenheid heeft geen naam" + } + }, + "question": "Wat is de naam van dit Klimgelegenheid?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "1": { + "then": "Klimsite {name}" + }, + "2": { + "then": "Klimsite" + }, + "3": { + "then": "Klimgelegenheid {name}" + } + }, + "render": "Klimgelegenheid" + } + }, + "climbing_club": { + "description": "Een klimclub of organisatie", + "name": "Klimclub", + "presets": { + "0": { + "description": "Een klimclub", + "title": "een klimclub" + }, + "1": { + "description": "Een VZW die werkt rond klimmen", + "title": "een een klimorganisatie" + } + }, + "tagRenderings": { + "climbing_club-name": { + "question": "Wat is de naam van deze klimclub?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Klimorganisatie" + } + }, + "render": "Klimclub" + } + }, + "climbing_gym": { + "description": "Een klimzaal", + "name": "Klimzalen", + "tagRenderings": { + "name": { + "question": "Wat is de naam van dit Klimzaal?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Klimzaal {name}" + } + }, + "render": "Klimzaal" + } + }, + "climbing_opportunity": { + "description": "Een klimgelegenheid?", + "name": "Klimgelegenheiden?", + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + }, + "climbing-possible": { + "mappings": { + "0": { + "then": "Klimmen is hier niet toegelaten" + }, + "1": { + "then": "Klimmen is hier niet toegelaten" + }, + "2": { + "then": "Klimmen is hier niet mogelijk" + } + } + } + }, + "title": { + "render": "Klimgelegenheid?" + } + }, + "climbing_route": { + "name": "Klimroute", + "presets": { + "0": { + "title": "een klimroute" + } + }, + "tagRenderings": { + "Difficulty": { + "question": "Hoe moeilijk is deze klimroute volgens het Franse/Belgische systeem?", + "render": "De klimmoeilijkheid is {climbing:grade:french} volgens het Franse/Belgische systeem" + }, + "Length": { + "question": "Hoe lang is deze klimroute (in meters)?", + "render": "Deze klimroute is {canonical(climbing:length)} lang" + }, + "Name": { + "mappings": { + "0": { + "then": "Deze klimroute heeft geen naam" + } + }, + "question": "Hoe heet deze klimroute?", + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Klimroute {name}" + } + }, + "render": "Klimroute" + } + }, "crab_address": { "tagRenderings": { "render_crab": { @@ -4459,6 +4607,22 @@ } }, "description": "Een winkel", + "filter": { + "0": { + "options": { + "0": { + "question": "Toon enkel winkels die {search} verkopen" + } + } + }, + "1": { + "options": { + "0": { + "question": "Toon enkel winkels met naam {search}" + } + } + } + }, "name": "Winkel", "presets": { "0": { @@ -4524,22 +4688,6 @@ } }, "render": "Winkel" - }, - "filter": { - "0": { - "options": { - "0": { - "question": "Toon enkel winkels die {search} verkopen" - } - } - }, - "1": { - "options": { - "0": { - "question": "Toon enkel winkels met naam {search}" - } - } - } } }, "slow_roads": { @@ -5606,5 +5754,41 @@ }, "render": "Watermolens" } + }, + "windturbine": { + "name": "windturbine", + "presets": { + "0": { + "title": "een windturbine" + } + }, + "title": { + "render": "windturbine" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " megawatt" + }, + "1": { + "human": " kilowatt" + }, + "2": { + "human": " watt" + }, + "3": { + "human": " gigawatt" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " meter" + } + } + } + } } -} +} \ No newline at end of file diff --git a/langs/layers/ru.json b/langs/layers/ru.json index 5377904ba..fca36af7e 100644 --- a/langs/layers/ru.json +++ b/langs/layers/ru.json @@ -763,6 +763,56 @@ } } }, + "climbing": { + "tagRenderings": { + "name": { + "render": "{name}" + } + } + }, + "climbing_club": { + "name": "Клуб скалолазания", + "presets": { + "0": { + "description": "Клуб скалолазания", + "title": "Клуб скалолазания" + } + }, + "tagRenderings": { + "climbing_club-name": { + "render": "{name}" + } + }, + "title": { + "render": "Клуб скалолазания" + } + }, + "climbing_gym": { + "description": "Комплекс скалолазания", + "name": "Комплексы скалолазания", + "tagRenderings": { + "name": { + "render": "{name}" + } + }, + "title": { + "render": "Комплекс скалолазания" + } + }, + "climbing_opportunity": { + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + } + } + }, + "climbing_route": { + "tagRenderings": { + "Name": { + "render": "{name}" + } + } + }, "crossings": { "presets": { "1": { @@ -949,6 +999,33 @@ "render": "Велосипед Ghost" } }, + "hackerspace": { + "description": "Хакерспейс", + "name": "Хакерспейс", + "presets": { + "0": { + "title": "Хакерспейс" + } + }, + "tagRenderings": { + "hackerspaces-opening_hours": { + "mappings": { + "0": { + "then": "Открыто 24/7" + } + }, + "render": "{opening_hours_table()}" + } + }, + "title": { + "mappings": { + "0": { + "then": " {name}" + } + }, + "render": "Хакерспейс" + } + }, "hydrant": { "description": "Слой карты, отображающий пожарные гидранты.", "name": "Карта пожарных гидрантов", @@ -1625,5 +1702,39 @@ }, "watermill": { "name": "Водяная мельница" + }, + "windturbine": { + "title": { + "mappings": { + "0": { + "then": "{name}" + } + } + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " мегаватт" + }, + "1": { + "human": " киловатт" + }, + "2": { + "human": " ватт" + }, + "3": { + "human": " гигаватт" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " метр" + } + } + } + } } } \ No newline at end of file diff --git a/langs/layers/zh_Hant.json b/langs/layers/zh_Hant.json index f1e931d5d..6a0ea50c1 100644 --- a/langs/layers/zh_Hant.json +++ b/langs/layers/zh_Hant.json @@ -457,6 +457,23 @@ "cafe_pub": { "name": "咖啡廳與酒吧" }, + "climbing_club": { + "description": "攀岩社團或組織", + "name": "攀岩社團", + "tagRenderings": { + "climbing_club-name": { + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "攀岩 NGO" + } + }, + "render": "攀岩社團" + } + }, "extinguisher": { "description": "顯示消防栓的地圖圖層。" }, @@ -471,8 +488,134 @@ "render": "幽靈單車" } }, + "hackerspace": { + "description": "駭客空間", + "name": "駭客空間", + "presets": { + "0": { + "description": "駭客空間是對軟體有興趣的人聚集的地方", + "title": "駭客空間" + }, + "1": { + "description": "創客空間是 DIY 愛好者聚集在一起弄電子零件實驗,例如用 arduino、LEDstrips 等...", + "title": "創客空間" + } + }, + "tagRenderings": { + "hackerspaces-name": { + "question": "這個駭客空間的名稱是?", + "render": "這個駭客空間叫 {name}" + }, + "hackerspaces-opening_hours": { + "mappings": { + "0": { + "then": "24/7 營業" + } + }, + "question": "這個駭客空間的營業時間?", + "render": "{opening_hours_table()}" + }, + "hackerspaces-start_date": { + "question": "這個駭客空間何時成立的?", + "render": "這駭客空間是 {start_date} 成立的" + }, + "hs-club-mate": { + "mappings": { + "0": { + "then": "這個駭客空間服務俱樂部伙伴" + }, + "1": { + "then": "這個駭客空間沒有服務俱樂部伙伴" + } + }, + "question": "這個駭客空間是否服務俱樂部伙伴?" + }, + "is_makerspace": { + "mappings": { + "0": { + "then": "這是創客空間" + }, + "1": { + "then": "這是傳統的 (軟體導向) 駭客空間" + } + }, + "question": "這邊是駭客空間還是創客空間?" + } + }, + "title": { + "mappings": { + "0": { + "then": " {name}" + } + }, + "render": "駭客空間" + } + }, "hydrant": { "description": "顯示消防栓的地圖圖層。", "name": "消防栓地圖" + }, + "windturbine": { + "name": "風機", + "presets": { + "0": { + "title": "風機" + } + }, + "tagRenderings": { + "turbine-diameter": { + "question": "這個風力渦輪機的風葉直徑是多少公尺?", + "render": "這個風力渦輪機的風葉直徑是 {rotor:diameter} 公尺。" + }, + "turbine-height": { + "question": "這個風機的總高度是多少 (包括風葉大小) 公尺?", + "render": "這風機的總高度 (包括風葉直徑) 是 {height} 公尺。" + }, + "turbine-operator": { + "question": "這個風機營業商是?", + "render": "這個風機營業商是 {operator}。" + }, + "turbine-output": { + "question": "這個風機的電力輸出是多少?(例如 2.3 MW)", + "render": "這個風機的電力輸出是 {generator:output:electricity}。" + }, + "turbine-start-date": { + "question": "這個風機何時開始營運?", + "render": "這個風機從 {start_date} 開始運轉。" + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "風機" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " 百萬瓦" + }, + "1": { + "human": " 千瓦" + }, + "2": { + "human": " 瓦" + }, + "3": { + "human": " 千兆瓦" + } + } + }, + "1": { + "applicableUnits": { + "0": { + "human": " 公尺" + } + } + } + } } } \ No newline at end of file diff --git a/langs/nl.json b/langs/nl.json index 3590a9022..a42df1994 100644 --- a/langs/nl.json +++ b/langs/nl.json @@ -97,17 +97,13 @@ "backToMapcomplete": "Terug naar het themaoverzicht", "backgroundMap": "Achtergrondkaart", "cancel": "Annuleren", - "centerMessage": { - "loadingData": "Data wordt geladen…", - "ready": "Klaar!", - "retrying": "Data inladen mislukt. Opnieuw proberen over {count} seconden…", - "zoomIn": "Zoom in om de data te zien en te bewerken" - }, "confirm": "Bevestigen", "customThemeIntro": "

    Onofficiële thema's

    De onderstaande thema's heb je eerder bezocht en zijn gemaakt door andere OpenStreetMappers.", "download": { "downloadAsPdf": "Download een PDF van de huidig zichtbare kaart", "downloadAsPdfHelper": "Perfect om de huidige kaart af te printen", + "downloadAsSvg": "Download de huidige kaart als SVG", + "downloadAsSvgHelper": "Compatibel met Inkscape of Adobe Illustrator; deze data moeten nog verder verwerkt worden… ", "downloadCSV": "Download de zichtbare data als CSV", "downloadCSVHelper": "Compatibel met LibreOffice Calc, Excel, …", "downloadFeatureAsGeojson": "Downloaden als GeoJson bestand", @@ -121,9 +117,7 @@ "licenseInfo": "

    Copyright

    De voorziene data is beschikbaar onder de ODbL. Het hergebruiken van deze data is gratis voor elke toepassing, maar
    • de bronvermelding © OpenStreetMap bijdragers is vereist
    • Elke wijziging aan deze data moet opnieuw gepubliceerd worden onder dezelfde licentie
    Gelieve de volledige licentie te lezen voor details", "noDataLoaded": "Er is nog geen data ingeladen. Downloaden kan zodra de data geladen is.", "title": "Download de zichtbare data", - "uploadGpx": "Track uploaden naar OpenStreetMap", - "downloadAsSvg": "Download de huidige kaart als SVG", - "downloadAsSvgHelper": "Compatibel met Inkscape of Adobe Illustrator; deze data moeten nog verder verwerkt worden… " + "uploadGpx": "Track uploaden naar OpenStreetMap" }, "example": "Voorbeeld", "examples": "Voorbeelden", @@ -134,18 +128,13 @@ "histogram": { "error_loading": "Kan het histogram niet laden" }, - "index": { - "#": "Deze teksten worden getoond boven de themaknoppen als er geen thema is geladen", - "intro": "MapComplete is een OpenStreetMap applicatie waar informatie over een specifiek thema bekeken en aangepast kan worden.", - "pickTheme": "Kies hieronder een thema om te beginnen.", - "title": "Welkom bij MapComplete" - }, "layerSelection": { "title": "Selecteer lagen", "zoomInToSeeThisLayer": "Vergroot de kaart om deze laag te zien" }, "loading": "Aan het laden...", "loadingTheme": "{theme} wordt geladen...", + "loginFailed": "Het inloggen op OpenStreetMap is gefaald", "loginOnlyNeededToEdit": "als je de kaart wilt aanpassen", "loginToStart": "Meld je aan om deze vraag te beantwoorden", "loginWithOpenStreetMap": "Aanmelden met OpenStreetMap", @@ -201,23 +190,8 @@ "readYourMessages": "Gelieve eerst je berichten op OpenStreetMap te lezen alvorens nieuwe punten toe te voegen.", "removeLocationHistory": "Verwijder de geschiedenis aan locaties", "returnToTheMap": "Ga terug naar de kaart", - "reviews": { - "affiliated_reviewer_warning": "(Review door betrokkene)", - "attribution": "De beoordelingen worden voorzien door Mangrove Reviews en zijn beschikbaar onder deCC-BY 4.0-licentie.", - "i_am_affiliated": "Ik ben persoonlijk betrokken
    Vink aan indien je de oprichter, maker, werknemer, ... of dergelijke bent", - "name_required": "De naam van dit object moet gekend zijn om een review te kunnen maken", - "no_rating": "Geen score bekend", - "no_reviews_yet": "Er zijn nog geen beoordelingen. Wees de eerste om een beoordeling te schrijven en help open data en het bedrijf!", - "plz_login": "Meld je aan om een beoordeling te geven", - "posting_as": "Ingelogd als", - "saved": "Bedankt om je beoordeling te delen!", - "saving_review": "Opslaan…", - "title": "{count} beoordelingen", - "title_singular": "Eén beoordeling", - "tos": "Als je je review publiceert, ga je akkoord met de de gebruiksvoorwaarden en privacy policy van Mangrove.reviews", - "write_a_comment": "Schrijf een beoordeling…" - }, "save": "Opslaan", + "screenToSmall": "Open {theme} in een nieuw venster", "search": { "error": "Niet gelukt...", "nothing": "Niet gevonden...", @@ -270,17 +244,15 @@ "doSearch": "Zoek hierboven om resultaten te zien", "failed": "Het Wikipedia-artikel inladen is mislukt", "loading": "Wikipedia aan het laden...", - "noResults": "Niet gevonden voor {search}", + "noResults": "Geen relevante items gevonden voor {search}", "noWikipediaPage": "Dit Wikidata-item heeft nog geen overeenkomstig Wikipedia-artikel", - "searchWikidata": "Zoek op Wikidata", - "wikipediaboxTitle": "Wikipedia", "previewbox": { "born": "Geboren: {value}", "died": "Gestorven: {value}" - } - }, - "loginFailed": "Het inloggen op OpenStreetMap is gefaald", - "screenToSmall": "Open {theme} in een nieuw venster" + }, + "searchWikidata": "Zoek op Wikidata", + "wikipediaboxTitle": "Wikipedia" + } }, "image": { "addPicture": "Voeg foto toe", @@ -304,43 +276,56 @@ "willBePublished": "Jouw foto wordt gepubliceerd " }, "importHelper": { - "allAttributesSame": "Alle kaart-objecten om te importeren hebben deze tag", - "loginIsCorrect": "{name} is de correcte account om de import-nota's mee te maken.", + "compareToAlreadyExistingNotes": { + "nothingNearby": "Geen enkel te importeren punt heeft een importeer-kaartnota in de buurt" + }, + "introduction": { + "description": "De importeer-helper converteert een externe dataset in OSM-kaartnotas. De externe data moet overeenkomen met een bestaande MapComplete-laag. Voor elk item wordt er een kaartnota gemaakt. Deze notas worden dan samen met de relevante POI getoond en kunnen dan (via MapComplete) snel en eenvoudig toegevoegd worden.", + "importFormat": "Een kaartnota moet het volgende formaat hebben om gedetecteerd te worden binnen een laag:
    [Een introductietekst]
    https://mapcomplete.osm.be/[themename].html?[parameters waaronder lon en lat]#import
    [alle tags van het te importeren object]
    " + }, + "login": { + "lockNotice": "Deze pagina is afgeschermd. Je hebt minstens {importHelperUnlock} changesets nodig voor je deze pagina mag gebruiken.", + "loggedInWith": "Je bent momenteel aangemeld als {name} and maakte {csCount} eerdere wijzigingen", + "loginIsCorrect": "{name} is de correcte account om de import-nota's mee te maken.", + "loginRequired": "Je moet ingelogd zijn om verder te gaan", + "userAccountTitle": "Selecteer een account" + }, "mapPreview": { "autodetected": "Deze laag was automatisch gekozen gebaseerd op de aanwezige eigenschappen", "confirm": "De objecten bevinden zich op de juiste locatie", - "title": "Voorbeeldkaart", "mismatch": "{count} objecten hebben niet de juiste tags. Zorg ervoor dat de juiste tags om het type aan te geven aanwezig zijn, namelijk {tags}", - "selectLayer": "Met welke laag komt deze te importeren dataset overeen?" + "selectLayer": "Met welke laag komt deze te importeren dataset overeen?", + "title": "Voorbeeldkaart" + }, + "noteParts": { + "datasource": "Oorspronkelijke data van {source}", + "importEasily": "Voeg dit punt eenvoudig toe met MapComplete:", + "wikilink": "Meer informatie over deze import: {wikilink}" + }, + "previewAttributes": { + "allAttributesSame": "Alle kaart-objecten om te importeren hebben deze tag", + "inspectDataTitle": "Bekijk de data van {count} te importeren objecten", + "inspectLooksCorrect": "Deze waardes zien er correct uit", + "someHaveSame": "{count} te importeren objecten hebben dit attribuut, dit is {percentage}% van het totaal" }, "selectFile": { "description": "Selecteer een .csv of .geojson-bestand", - "errNoLatOrLon": "Geen enkele kolom heet `lat` of `lon`", - "errPointsOnly": "Het ingeladen JSON-bestand mag enkel punten bevatten", "errDuplicate": "Sommige kolommen hebben dezelfde naam", + "errNoLatOrLon": "Geen enkele kolom heet `lat` of `lon`", "errNoName": "De naam van sommige kolommen ontbreken", "errNotFeatureCollection": "Het ingeladen JSON-bestand is geen geojson-featurecollection", + "errPointsOnly": "Het ingeladen JSON-bestand mag enkel punten bevatten", "fileFormatDescription": "Selecteer een .csv- of een .geojsonbestand", + "fileFormatDescriptionCsv": "Het CSV-bestand moet een kolom lat en lon bevatten die de coordinaten in WGS84 beschrijft. Bovendien moet er voor elk attribuut nog een kolom zijn..", + "fileFormatDescriptionGeoJson": "Het geojson-bestand mag enkel punten bevatten. De attributen moeten dezelfde zijn zoals in OpenStreetMap", "loadedFilesAre": "{file} werd ingeladen", "noFilesLoaded": "Geen bestand ingeladen op dit moment", - "title": "Selecteer bestand", - "fileFormatDescriptionCsv": "Het CSV-bestand moet een kolom lat en lon bevatten die de coordinaten in WGS84 beschrijft. Bovendien moet er voor elk attribuut nog een kolom zijn..", - "fileFormatDescriptionGeoJson": "Het geojson-bestand mag enkel punten bevatten. De attributen moeten dezelfde zijn zoals in OpenStreetMap" + "title": "Selecteer bestand" }, - "inspectDataTitle": "Bekijk de data van {count} te importeren objecten", - "lockNotice": "Deze pagina is afgeschermd. Je hebt minstens {importHelperUnlock} changesets nodig voor je deze pagina mag gebruiken.", - "description": "De importeer-helper converteert een externe dataset in OSM-kaartnotas. De externe data moet overeenkomen met een bestaande MapComplete-laag. Voor elk item wordt er een kaartnota gemaakt. Deze notas worden dan samen met de relevante POI getoond en kunnen dan (via MapComplete) snel en eenvoudig toegevoegd worden.", - "inspectDidAutoDected": "Deze laag werd automatisch gekozen", - "importFormat": "Een kaartnota moet het volgende formaat hebben om gedetecteerd te worden binnen een laag:
    [Een introductietekst]
    https://mapcomplete.osm.be/[themename].html?[parameters waaronder lon en lat]#import
    [alle tags van het te importeren object]
    ", - "inspectLooksCorrect": "Deze waardes zien er correct uit", - "locked": "Je hebt minstens {importHelperUnlock} changesets nodig om de import helper te gebruiken", - "loggedInWith": "Je bent momenteel aangemeld als {name} and maakte {csCount} eerdere wijzigingen", - "loginRequired": "Je moet ingelogd zijn om verder te gaan", - "title": "Importeer-helper", - "selectLayer": "Selecteer een laag...", - "validateDataTitle": "Valideer data", - "someHaveSame": "{count} te importeren objecten hebben dit attribuut, dit is {percentage}% van het totaal", - "userAccountTitle": "Selecteer een account" + "title": "Importeer-helper" + }, + "importInspector": { + "title": "Inspecteer en beheer importeer-notas" }, "importLayer": { "alreadyMapped": "Er staat hier reeds een {title} op de kaart; dit punt is een duplicaat. Verwijder deze van de kaart", @@ -388,6 +373,8 @@ "autoApply": "Wijzigingen aan eigenschappen {attr_names} zullen ook worden uitgevoerd op {count} andere objecten." }, "notes": { + "addAComment": "Voeg een commentaar toe", + "addComment": "Voeg commentaar toe", "addCommentAndClose": "Voeg een commentaar toe en sluit de nota", "addCommentPlaceholder": "Voeg een commentaar toe...", "anonymous": "Anonieme bijdrager", @@ -395,24 +382,22 @@ "createNote": "Maak een nieuwe kaartnota", "createNoteIntro": "Ontbreekt hier iets? Is hier iets mis met de kaart? Maak hier dan een kaartnota, deze zal door vrijwilligers verwerkt worden.", "createNoteTitle": "Voeg hier een nieuwe kaartnota toe", - "textNeeded": "Geef een beschrijvende tekst om een kaartnota te maken", - "typeText": "Typ eerst een commentaar om deze toe te voegen", "disableAllNoteFilters": "Schakel alle filters uit", + "isClosed": "Deze nota is gesloten", + "isCreated": "Je kaarnota werd gemaakt!", + "loginToAddComment": "Log in om een commentaar toe te voegen", + "loginToAddPicture": "Log in om een afbeelding toe te voegen", + "loginToClose": "Login om deze kaartnota te sluiten", + "noteIsPublic": "Dit zal voor iedereen zichtbaar zijn", + "noteLayerDoEnable": "Schakel de laat met kaartnota's in", "noteLayerHasFilters": "Sommige kaartnota's kunnen verborgen zijn door een filter", "noteLayerNotEnabled": "De laat met kaartnota's staat af. Zet deze aan om een nieuwe kaartnota toe te voegen", "notesLayerMustBeEnabled": "De laat met kaartnota's staat af. Zet deze aan om een nieuwe kaartnota toe te voegen", "reopenNote": "Heropen de kaartnota", - "addComment": "Voeg commentaar toe", - "noteIsPublic": "Dit zal voor iedereen zichtbaar zijn", - "addAComment": "Voeg een commentaar toe", - "isClosed": "Deze nota is gesloten", - "loginToAddComment": "Log in om een commentaar toe te voegen", - "loginToAddPicture": "Log in om een afbeelding toe te voegen", - "loginToClose": "Login om deze kaartnota te sluiten", - "noteLayerDoEnable": "Schakel de laat met kaartnota's in", - "isCreated": "Je kaarnota werd gemaakt!", - "warnAnonymous": "Je bent niet aangemeld. We gaan je niet kunnen contacteren om deze kaartnota te verwerken.", - "reopenNoteAndComment": "Heropen de kaartnota en voeg commentaar toe" + "reopenNoteAndComment": "Heropen de kaartnota en voeg commentaar toe", + "textNeeded": "Geef een beschrijvende tekst om een kaartnota te maken", + "typeText": "Typ eerst een commentaar om deze toe te voegen", + "warnAnonymous": "Je bent niet aangemeld. We gaan je niet kunnen contacteren om deze kaartnota te verwerken." }, "privacy": { "editing": "Wanneer je een wijziging maakt, wordt deze wijziging opgeslaan op OpenStreetMap. Dit is zichtbaar voor iedereen. Een wijzigingenset gemaakt met MapComplete bevat de volgende data:\n
    • De aanpassingen aan de data
    • Je gebruikersnaam
    • Wanneer deze wijziging werd gemaakt
    • Het thema dat je gebruikt om de wijziging te maken
    • De taal van de gebruikersinterface
    • Een indicatie hoe ver jij je van de gewijzigde objecten bevindt. Andere bijdragers kunnen deze informatie gebruiken om af te leiden of de wijziging gemaakt door lokaal te gaan kijken of door onderzoek vanop afstand
    Bekijk ook de privacy-policy op OpenStreetMap.org voor gedetailleerde info. We herinneren je eraan dat je een pseudoniem of fictieve naam kan gebruiken wanneer je je registreert.", @@ -443,7 +428,7 @@ "title": "Mogelijkheden om data te verzamelen" }, "text0": "Als je een bestaand MapComplete-thema wilt gebruiken of in je website wilt embedden, dan mag je dit gratis doen. Dit is gratis en zal dat altijd zijn.", - "text1": "Wil je andere data visualiseren, maar bestaat er nog geen geschikte kaart voor? De MapComplete-ontwikkelaars kunnen dit op maat bouwen voor een schappelijk budget. Stuur je vraag via email, github of een bericht op osm.org", + "text1": "Wil je andere data visualiseren, maar bestaat er nog geen geschikte kaart voor? De MapComplete-ontwikkelaars kunnen dit op maat bouwen voor een schappelijk budget. Stuur je vraag via email, github of een bericht op osm.org", "text2": "Twijfel je nog? We sommen de mogelijkheden hieronder op en beantwoorden enkele veelvoorkomende vragen", "title": "MapComplete gebruiken in je eigen organisatie" }, @@ -482,6 +467,17 @@ }, "drawbacks": { "intro": "Aansluiten bij de OpenStreetMap-community heeft veel voordelen, toch zijn er enkele punten om rekening mee te houden.", + "licenseNuances": { + "intro": "OpenStreetMap wordt verspreid met de Open Database License. Deze houdt in dat:", + "li0": "Alle data mag hergebruikt worden voor alle doeleinden - inclusief commercieel gebruik", + "li1": "Applicaties en producten die OpenStreetMap gebruiken moeten een attributie tonen", + "li2": "Een dataset of kaartproduct die OpenStreetMap-data bevat moet deze data herpubliceren onder de ODbL, inclusief aanpassingen aan de data in een algemeen bruikbaar formaat.", + "outro": "Dit heeft enkele gevolgen voor sommige toepassingen zoals hieronder uitgelegd", + "title": "Gevolgen van de ODbL voor enkele toepassingen", + "usecaseGatheringOpenData": { + "title": "Het verzamelen van Open Data" + } + }, "title": "Enkele nadelen om rekening mee te houden", "unsuitedData": { "intro": "De basisregel is dat alle gegevens ter plaatse verifieerbaar moeten en ietwat permanent moeten zijn. Dit betekent dat sommige data niet in OpenStreetMap opgeslaan mogen worden - al bestaan hier oplossingen voor.", @@ -489,17 +485,6 @@ "li1": "Gebeurtenissen horen niet thuis in OpenStreetMap, net zoals kortstondige wegenwerken van enkele dagen of weken.", "li2": "Tijdsgebonden data (bv. statistieken van luchtkwaliteit, verkeersintensiteit, ...) kunnen niet bewaard worden op OpenStreetMap. Merk echter op dat MapComplete dit soort data kan visualiseren indien deze op een andere locatie opgeslaan is.", "title": "Data die niet geschikt is voor OpenStreetMap" - }, - "licenseNuances": { - "li0": "Alle data mag hergebruikt worden voor alle doeleinden - inclusief commercieel gebruik", - "li1": "Applicaties en producten die OpenStreetMap gebruiken moeten een attributie tonen", - "li2": "Een dataset of kaartproduct die OpenStreetMap-data bevat moet deze data herpubliceren onder de ODbL, inclusief aanpassingen aan de data in een algemeen bruikbaar formaat.", - "outro": "Dit heeft enkele gevolgen voor sommige toepassingen zoals hieronder uitgelegd", - "title": "Gevolgen van de ODbL voor enkele toepassingen", - "intro": "OpenStreetMap wordt verspreid met de Open Database License. Deze houdt in dat:", - "usecaseGatheringOpenData": { - "title": "Het verzamelen van Open Data" - } } }, "indexPage": { @@ -546,14 +531,26 @@ }, "translations": { "activateButton": "Help met het vertalen van MapComplete", + "completeness": "Vertalingen voor {theme} in {language} zijn momenteel op {percentage}%: van {total} teksten zijn er reeds {translated} vertaald", "deactivate": "Verberg de vertaalknoppen", "help": "Klik op het 'vertaal'-icoontje die naast een stukje tekst staat om deze tekst te vertalen of aan te passen. Hiervoor heb je een (gratis) Weblate-account nodig. Indien je jouw account maakt met dezelfde naam als je OSM-gebruikersnaam, dan zullen de vertaalknoppen automatisch verschijnen.", "isTranslator": "Vertaalmode is actief: je gebruikersnaam is dezelfde als van een vertaler. We gaan er dus vanuit dat jij die vertaler bent", "missing": "{count} niet-vertaalde teksten", - "notImmediate": "Vertalingen worden niet onmiddelijk geupdate. Dit duurt gemiddeld enkele dagen", - "completeness": "Vertalingen voor {theme} in {language} zijn momenteel op {percentage}%: van {total} teksten zijn er reeds {translated} vertaald" + "notImmediate": "Vertalingen worden niet onmiddelijk geupdate. Dit duurt gemiddeld enkele dagen" }, "validation": { + "color": { + "description": "Een kleur of hexadecimale code voor een kleur" + }, + "date": { + "description": "Een datum (beginnend met het jaar)" + }, + "decimal": { + "description": "Een getal" + }, + "direction": { + "description": "Een orientatie" + }, "email": { "description": "email-adres", "feedback": "Dit is geen geldig email-adres", @@ -572,6 +569,9 @@ "mustBeWhole": "Enkele gehele getallen zijn toegelaten", "notANumber": "Dit is geen getal" }, + "opening_hours": { + "description": "Openingsuren" + }, "pfloat": { "description": "een positief getal" }, @@ -586,34 +586,16 @@ "string": { "description": "een stukje tekst" }, + "text": { + "description": "Een stukje tekst" + }, "tooLong": "Deze tekst is te lang. De tekst heeft {count} lettertekens, er mogen maximaal 255 letters zijn", "url": { "description": "een link naar een webpagina", "feedback": "Dit is geen geldige link" }, - "color": { - "description": "Een kleur of hexadecimale code voor een kleur" - }, - "direction": { - "description": "Een orientatie" - }, - "opening_hours": { - "description": "Openingsuren" - }, - "text": { - "description": "Een stukje tekst" - }, - "date": { - "description": "Een datum (beginnend met het jaar)" - }, - "decimal": { - "description": "Een getal" - }, "wikidata": { "description": "Een Wikidata-code" } - }, - "importInspector": { - "title": "Inspecteer en beheer importeer-notas" } } diff --git a/langs/pl.json b/langs/pl.json index 2f7a400ad..507e99316 100644 --- a/langs/pl.json +++ b/langs/pl.json @@ -35,121 +35,9 @@ "cancel": "Anuluj", "customThemeIntro": "

    Motywy własne

    Są to wcześniej odwiedzone motywy stworzone przez użytkowników.", "fewChangesBefore": "Proszę odpowiedzieć na kilka pytań dotyczących istniejących punktów przed dodaniem nowego punktu.", - "general": { - "about": "Łatwo edytuj i dodaj OpenStreetMap dla określonego motywu", - "aboutMapcomplete": "

    O MapComplete

    Dzięki MapComplete możesz wzbogacić OpenStreetMap o informacje na pojedynczy temat. Odpowiedz na kilka pytań, a w ciągu kilku minut Twój wkład będzie dostępny na całym świecie! Opiekun tematu definiuje elementy, pytania i języki dla tematu.

    Dowiedz się więcej

    MapComplete zawsze oferuje następny krok, by dowiedzieć się więcej o OpenStreetMap.

    • Po osadzeniu na stronie internetowej, element iframe łączy się z pełnoekranowym MapComplete
    • Wersja pełnoekranowa oferuje informacje o OpenStreetMap
    • Przeglądanie działa bez logowania, ale edycja wymaga loginu OSM.
    • Jeżeli nie jesteś zalogowany, zostaniesz poproszony o zalogowanie się
    • Po udzieleniu odpowiedzi na jedno pytanie, możesz dodać nowe punkty do mapy
    • Po chwili wyświetlane są rzeczywiste tagi OSM, które później linkują do wiki


    Zauważyłeś problem? Czy masz prośbę o dodanie jakiejś funkcji? Chcesz pomóc w tłumaczeniu? Udaj się do kodu źródłowego lub issue trackera.

    Chcesz zobaczyć swoje postępy? Śledź liczbę edycji na OsmCha.

    ", - "add": { - "addNew": "Dodaj nową {category} tutaj", - "confirmButton": "Dodaj tutaj {category}.
    Twój dodatek jest widoczny dla wszystkich
    ", - "confirmIntro": "

    Czy dodać tutaj {title}?

    Punkt, który tutaj utworzysz, będzie widoczny dla wszystkich. Proszę, dodawaj rzeczy do mapy tylko wtedy, gdy naprawdę istnieją. Wiele aplikacji korzysta z tych danych.", - "intro": "Kliknąłeś gdzieś, gdzie nie są jeszcze znane żadne dane.
    ", - "layerNotEnabled": "Warstwa {layer} nie jest włączona. Włącz tę warstwę, aby dodać punkt", - "openLayerControl": "Otwórz okno sterowania warstwą", - "pleaseLogin": "Zaloguj się, aby dodać nowy punkt", - "stillLoading": "Dane wciąż się ładują. Poczekaj chwilę, zanim dodasz nowy punkt.", - "title": "Czy dodać nowy punkt?", - "zoomInFurther": "Powiększ jeszcze bardziej, aby dodać punkt." - }, - "backgroundMap": "Tło mapy", - "cancel": "Anuluj", - "customThemeIntro": "

    Motywy własne

    Są to wcześniej odwiedzone motywy stworzone przez użytkowników.", - "fewChangesBefore": "Proszę odpowiedzieć na kilka pytań dotyczących istniejących punktów przed dodaniem nowego punktu.", - "getStartedLogin": "Zaloguj się za pomocą OpenStreetMap, aby rozpocząć", - "getStartedNewAccount": " lub utwórz nowe konto", - "goToInbox": "Otwórz skrzynkę odbiorczą", - "layerSelection": { - "title": "Wybierz warstwy", - "zoomInToSeeThisLayer": "Powiększ, aby zobaczyć tę warstwę" - }, - "loginToStart": "Zaloguj się, aby odpowiedzieć na to pytanie", - "loginWithOpenStreetMap": "Zaloguj z OpenStreetMap", - "nameInlineQuestion": "Nazwa tej {category} to $$$", - "noNameCategory": "{category} bez nazwy", - "noTagsSelected": "Nie wybrano tagów", - "number": "numer", - "oneSkippedQuestion": "Jedno pytanie zostało pominięte", - "opening_hours": { - "closed_permanently": "Zamknięte na nieokreślony czas", - "closed_until": "Zamknięte do {date}", - "error_loading": "Błąd: nie można zwizualizować tych godzin otwarcia.", - "not_all_rules_parsed": "Godziny otwarcia tego sklepu są skomplikowane. Następujące reguły są ignorowane w elemencie wejściowym:", - "openTill": "do", - "open_24_7": "Otwarte przez całą dobę", - "open_during_ph": "W czasie świąt państwowych udogodnienie to jest", - "opensAt": "z", - "ph_closed": "zamknięte", - "ph_not_known": " ", - "ph_open": "otwarte" - }, - "osmLinkTooltip": "Zobacz ten obiekt na OpenStreetMap, aby uzyskać historię i więcej opcji edycji", - "pickLanguage": "Wybierz język: ", - "questions": { - "emailIs": "Adres e-mail {category} to {email}", - "emailOf": "Jaki jest adres e-mail {category}?", - "phoneNumberIs": "Numer telefonu {category} to {phone}", - "phoneNumberOf": "Jaki jest numer telefonu do {category}?", - "websiteIs": "Strona internetowa: {website}", - "websiteOf": "Jaka jest strona internetowa {category}?" - }, - "readYourMessages": "Przeczytaj wszystkie wiadomości OpenStreetMap przed dodaniem nowego punktu.", - "returnToTheMap": "Wróć do mapy", - "save": "Zapisz", - "search": { - "error": "Coś poszło nie tak…", - "nothing": "Nic nie znaleziono…", - "search": "Wyszukaj lokalizację", - "searching": "Szukanie…" - }, - "sharescreen": { - "addToHomeScreen": "

    Dodaj do ekranu głównego

    Możesz łatwo dodać tę stronę do ekranu głównego smartfona, aby poczuć się jak w domu. Kliknij przycisk \"Dodaj do ekranu głównego\" na pasku adresu URL, aby to zrobić.", - "copiedToClipboard": "Link został skopiowany do schowka", - "editThemeDescription": "Dodaj lub zmień pytania do tego motywu mapy", - "editThisTheme": "Edytuj ten motyw", - "embedIntro": "

    Umieść na swojej stronie internetowej

    Proszę, umieść tę mapę na swojej stronie internetowej.
    Zachęcamy cię do tego - nie musisz nawet pytać o zgodę.
    Jest ona darmowa i zawsze będzie. Im więcej osób jej używa, tym bardziej staje się wartościowa.", - "fsAddNew": "Włącz przycisk \"Dodaj nowe POI\"", - "fsGeolocation": "Włącz przycisk „Zlokalizuj mnie” (tylko na urządzeniach mobilnych)", - "fsIncludeCurrentBackgroundMap": "Dołącz bieżący wybór tła {name}", - "fsIncludeCurrentLayers": "Uwzględnij wybór bieżącej warstwy", - "fsIncludeCurrentLocation": "Uwzględnij bieżącą lokalizację", - "fsLayerControlToggle": "Zacznij od rozwiniętej kontroli warstw", - "fsLayers": "Włącz kontrolę warstw", - "fsSearch": "Włącz pasek wyszukiwania", - "fsUserbadge": "Włącz przycisk logowania", - "fsWelcomeMessage": "Pokaż wyskakujące okienko wiadomości powitalnej i powiązane zakładki", - "intro": "

    Udostępnij tę mapę

    Udostępnij tę mapę, kopiując poniższy link i wysyłając ją do przyjaciół i rodziny:", - "thanksForSharing": "Dzięki za udostępnienie!" - }, - "skip": "Pomiń to pytanie", - "skippedQuestions": "Niektóre pytania są pominięte", - "weekdays": { - "abbreviations": { - "friday": "Pt", - "monday": "Pn", - "saturday": "Sob", - "sunday": "Niedz", - "thursday": "Czw", - "tuesday": "Wt", - "wednesday": "Śr" - }, - "friday": "Piątek", - "monday": "Poniedziałek", - "saturday": "Sobota", - "sunday": "Niedziela", - "thursday": "Czwartek", - "tuesday": "Wtorek", - "wednesday": "Środa" - }, - "welcomeBack": "Jesteś zalogowany, witaj z powrotem!" - }, "getStartedLogin": "Zaloguj się za pomocą OpenStreetMap, aby rozpocząć", "getStartedNewAccount": " lub utwórz nowe konto", "goToInbox": "Otwórz skrzynkę odbiorczą", - "index": { - "#": "Te teksty są wyświetlane nad przyciskami motywu, gdy nie jest załadowany żaden motyw", - "intro": "MapComplete to przeglądarka i edytor OpenStreetMap, który pokazuje informacje podzielone według tematu.", - "pickTheme": "Wybierz temat poniżej, aby rozpocząć.", - "title": "Witaj w MapComplete" - }, "layerSelection": { "title": "Wybierz warstwy", "zoomInToSeeThisLayer": "Powiększ, aby zobaczyć tę warstwę" diff --git a/langs/shared-questions/da.json b/langs/shared-questions/da.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/langs/shared-questions/da.json @@ -0,0 +1 @@ +{} diff --git a/langs/shared-questions/de.json b/langs/shared-questions/de.json index 72e726e99..12d4cab88 100644 --- a/langs/shared-questions/de.json +++ b/langs/shared-questions/de.json @@ -128,4 +128,4 @@ "question": "Was ist der entsprechende Artikel auf Wikipedia?" } } -} +} \ No newline at end of file diff --git a/langs/shared-questions/es.json b/langs/shared-questions/es.json index e513f074e..f6b0d6ad5 100644 --- a/langs/shared-questions/es.json +++ b/langs/shared-questions/es.json @@ -10,8 +10,122 @@ }, "1": { "then": "No se permiten perros" + }, + "2": { + "then": "Los perros están permitidos, pero tienen que llevar correa" + }, + "3": { + "then": "Los perros están permitidos y pueden estar sueltos" + } + }, + "question": "¿Están permitidos los perros en este negocio?" + }, + "email": { + "question": "¿Cual es la direccióm de correo electrónico de {title()}?" + }, + "level": { + "mappings": { + "0": { + "then": "Localizado bajo tierra" + }, + "1": { + "then": "Localizado en la planta baja" + }, + "2": { + "then": "Localizado en la planta baja" + }, + "3": { + "then": "Localizado en la primera planta" + }, + "4": { + "then": "Situado en el primer nivel del sótano" + } + }, + "question": "¿En qué nivel se encuentra esta característica?", + "render": "Localizada en la {level}° planta" + }, + "opening_hours": { + "question": "¿Cuales son las horas de apertura de {title()}?", + "render": "

    Horas de apertura

    {opening_hours_table(opening_hours)}" + }, + "payment-options": { + "mappings": { + "0": { + "then": "Aquí se acepta el pago en efectivo" + }, + "1": { + "then": "Aquí se acepta el pago por tarjeta" + } + }, + "question": "¿Qué métodos de pago se aceptan aquí?" + }, + "payment-options-advanced": { + "override": { + "mappings+": { + "0": { + "then": "El pago se realiza con una aplicación dedicada" + }, + "1": { + "then": "El pago se realiza con una tarjeta de membresía" + } } } + }, + "phone": { + "question": "¿Cuál es el número de teléfono de {title()}?" + }, + "service:electricity": { + "mappings": { + "0": { + "then": "Hay numerosos enchufes domésticos disponibles para los clientes sentados en el interior, donde pueden cargar sus dispositivos electrónicos" + }, + "1": { + "then": "Hay algunos enchufes domésticos disponibles para los clientes sentados en el interior, donde pueden cargar sus dispositivos electrónicos" + }, + "2": { + "then": "No hay enchufes disponibles en el interior para los clientes, pero cargar puede ser posible si se pregunta al personal" + }, + "3": { + "then": "No hay enchufes domésticos disponibles para los clientes sentados en el interior" + } + }, + "question": "¿Esta facilidad tiene enchufes eléctricos, disponibles para los clientes cuando están dentro?" + }, + "website": { + "question": "¿Cual es el sitio web de {title()}?" + }, + "wheelchair-access": { + "mappings": { + "0": { + "then": "Este lugar está especialmente adaptado para usuarios en sillas de ruedas" + }, + "1": { + "then": "Este lugar es fácilmente accesible con una silla de ruedas" + }, + "2": { + "then": "Es posible llegar a este lugar con una silla de ruedas, pero no es fácil" + }, + "3": { + "then": "No es posible llegar a este lugar con una silla de ruedas" + } + }, + "question": "¿Este lugar es accesible con una silla de ruedas?" + }, + "wikipedia": { + "mappings": { + "0": { + "then": "Todavía no se ha enlazado una página de wikipedia" + } + }, + "question": "¿Cual es la entidad de Wikidata que se corresponde?" + }, + "wikipedialink": { + "mappings": { + "0": { + "then": "No enlazado con Wikipedia" + } + }, + "question": "¿Cual es el ítem correspondiente en Wikipedia?" } } } \ No newline at end of file diff --git a/langs/shared-questions/fil.json b/langs/shared-questions/fil.json index 0967ef424..b309410c5 100644 --- a/langs/shared-questions/fil.json +++ b/langs/shared-questions/fil.json @@ -1 +1,131 @@ -{} +{ + "shared_questions": { + "description": { + "question": "Mayroon pa bang mga bagay na nau-ugnay at hindi mo maibigay sa mga nakaraang tanong? Idagdag dito.
    Huwag ulitin ang mga nai-saad na" + }, + "dog-access": { + "mappings": { + "0": { + "then": "Pinapayagan ang mga aso" + }, + "1": { + "then": "Hindi pinapayagan ang mga aso" + }, + "2": { + "then": "Pinapayagan ang mga aso kung may tali" + }, + "3": { + "then": "Pinapayayagan ang mga aso, at malayang makatatakbo" + } + }, + "question": "Pinapayagan ba ang mga aso sa establisyementong ito?" + }, + "email": { + "question": "Ano ang email address ng {title()}?" + }, + "level": { + "mappings": { + "0": { + "then": "Nasa ilalim ng lupa" + }, + "1": { + "then": "Nasa unang palapag" + }, + "2": { + "then": "Nasa unang palapag" + }, + "3": { + "then": "Nasa unang palapag" + }, + "4": { + "then": "Nasa silong" + } + }, + "question": "Anong palapag matatagpuan ang tampók?", + "render": "Natagpuan sa ika-{level} na palapag" + }, + "opening_hours": { + "question": "Anong oras nagbubukas ang {title()}?", + "render": "

    Mga oras na bukas

    {opening_hours_table(opening_hours)}" + }, + "payment-options": { + "mappings": { + "0": { + "then": "Tinatanggap ang salapi rito" + }, + "1": { + "then": "Tinatanggap ang mga tarhetang pambayad dito" + } + }, + "question": "Anong mga paraang pambayad ang tinatanggap dito?" + }, + "payment-options-advanced": { + "override": { + "mappings+": { + "0": { + "then": "Binabayaran gamit ang sariling app" + }, + "1": { + "then": "Binabayaran gamit ang membership card" + } + } + } + }, + "phone": { + "question": "Ano ang telepono ng {title()}?" + }, + "service:electricity": { + "mappings": { + "0": { + "then": "Maraming mga intsupe (sockets) na maaring gamitin ng mga suki na nakaupo sa loob, pang-karga ng kanilang mga elektroniks" + }, + "1": { + "then": "May iilang mga intsupe (sockets) na maaring gamitin ng mga suki na nakaupo sa loob, pang-karga ng kanilang mga elektroniks" + }, + "2": { + "then": "Walang mga intsupe (socket) para sa mga suki, pero maaring tanungin ang kawani kung magpapa-karga" + }, + "3": { + "then": "Walang mga intsupe (socket) para sa mga suking nakaubo sa loob" + } + }, + "question": "Merong bang mga intsupe (outlet) sa loob, para sa mga suki?" + }, + "website": { + "question": "Ano ang website ng {title()}?" + }, + "wheelchair-access": { + "mappings": { + "0": { + "then": "Ang lugar na ito ay angkop sa mga gumagamit ng wheelchair" + }, + "1": { + "then": "Ang lugar na ito ay kayang abutin ng mga naka-wheelchair" + }, + "2": { + "then": "Kayang abutin ang lugar na ito ng mga naka-wheelchair, pero hindi madali" + }, + "3": { + "then": "Ang lugar na ito ay hindi kayang abutin ng naka-wheelchair" + } + }, + "question": "Kaya bang abutin ang lugar na ito ng naka-wheelchair?" + }, + "wikipedia": { + "mappings": { + "0": { + "then": "Wala pang kawing ng Wikipedia page" + } + }, + "question": "Ano ang nau-ukol na entidad sa Wikidata?" + }, + "wikipedialink": { + "mappings": { + "0": { + "then": "Hindi naka-ugnay sa Wikipedia" + } + }, + "question": "Ano ang nau-ukol na partida sa Wikipedia?" + } + } +} \ No newline at end of file diff --git a/langs/shared-questions/nb_NO.json b/langs/shared-questions/nb_NO.json index 7b1497c6e..e768c96d8 100644 --- a/langs/shared-questions/nb_NO.json +++ b/langs/shared-questions/nb_NO.json @@ -54,6 +54,15 @@ }, "question": "Hvilke betalingsmetoder godtas her?" }, + "payment-options-advanced": { + "override": { + "mappings+": { + "1": { + "then": "Betaling utføres med et medlemskort" + } + } + } + }, "phone": { "question": "Hva er telefonnummeret til {title()}?" }, diff --git a/langs/shared-questions/zh_Hans.json b/langs/shared-questions/zh_Hans.json new file mode 100644 index 000000000..a6422ac1b --- /dev/null +++ b/langs/shared-questions/zh_Hans.json @@ -0,0 +1,73 @@ +{ + "shared_questions": { + "dog-access": { + "mappings": { + "0": { + "then": "允许犬只" + }, + "1": { + "then": "允许犬只" + }, + "2": { + "then": "允许犬只,但必须拴绳" + }, + "3": { + "then": "允许犬只,且可自由放养" + } + }, + "question": "犬只是否在这个商业体中允许?" + }, + "email": { + "question": "{title()} 的电子邮箱地址为何?" + }, + "opening_hours": { + "question": "{title()} 的开放时间为何?", + "render": "

    开放时间

    {opening_hours_table(opening_hours)}" + }, + "payment-options": { + "mappings": { + "0": { + "then": "可用现金" + }, + "1": { + "then": "可用信用卡" + } + }, + "question": "这里支持哪些支付方式?" + }, + "payment-options-advanced": { + "override": { + "mappings+": { + "0": { + "then": "使用专用APP支付" + }, + "1": { + "then": "使用会员卡支付" + } + } + } + }, + "phone": { + "question": "{title()} 的电话号码为何?" + }, + "website": { + "question": "{title()} 的网站为何?" + }, + "wikipedia": { + "mappings": { + "0": { + "then": "尚未有连接到的维基百科页面" + } + }, + "question": "在Wikidata上对应的实体是什么?" + }, + "wikipedialink": { + "mappings": { + "0": { + "then": "不要连接到维基百科" + } + }, + "question": "在维基百科上对应的条目是什么?" + } + } +} \ No newline at end of file diff --git a/langs/themes/ca.json b/langs/themes/ca.json index 475988277..4fe033415 100644 --- a/langs/themes/ca.json +++ b/langs/themes/ca.json @@ -3,47 +3,284 @@ "description": "En aquest mapa , qualsevol pot trobar i marcar els desfibril·ladors externs automàtics més propers", "title": "Mapa obert de desfibril·ladors (DEA)" }, - "climbing": { + "artwork": { + "description": "Benvingut a Open Artwork Map, un mapa d'estàtues, busts, grafitis i altres obres d'art del tot el món", + "title": "Open Artwork Map" + }, + "benches": { + "description": "Aquest mapa mostra tots els bancs que hi ha a OpenStreetMap: bancs individuals i els bancs que hi ha a parades o refugis de transport públic. Amb un compte d'OpenStreetMap pots afegir nous bancs o editar detalls dels existents.", + "shortDescription": "Un mapa de bancs", + "title": "Bancs" + }, + "bicycle_rental": { + "title": "Lloguer de bicicletes" + }, + "bookcases": { + "title": "Open Bookcase Map" + }, + "cafes_and_pubs": { + "description": "Bars i pubs", + "title": "Cafés i bars" + }, + "campersite": { "layers": { "0": { - "tagRenderings": { - "climbing_club-name": { - "render": "{name}" + "description": "llocs d'acampada", + "name": "Llocs d'acampada", + "presets": { + "0": { + "title": "un lloc d'acampada" } - } - }, - "1": { + }, "tagRenderings": { - "name": { - "render": "{name}" - } - } - }, - "2": { - "tagRenderings": { - "Name": { - "render": "{name}" - } - } - }, - "3": { - "tagRenderings": { - "name": { - "render": "{name}" - } - } - }, - "4": { - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" + "caravansites-internet": { + "mappings": { + "0": { + "then": "Hi ha accés a internet" + } + } } } } + }, + "title": "Llocs d'acampada" + }, + "charging_stations": { + "title": "Estacions de càrrega" + }, + "climbing": { + "overrideAll": { + "tagRenderings+": { + "2": { + "mappings": { + "2": { + "then": "Només clients" + }, + "3": { + "then": "Només membres del club" + } + } + } + }, + "units+": { + "0": { + "applicableUnits": { + "0": { + "human": " metre" + }, + "1": { + "human": " peus" + } + } + } + } + }, + "title": "Open Climbing Map" + }, + "cycle_highways": { + "layers": { + "0": { + "name": "vies ciclistes", + "title": { + "render": "via ciclista" + } + } + }, + "title": "Vies ciclistes" + }, + "cycle_infra": { + "title": "Infraestructura per a bicicletes" + }, + "cyclenodes": { + "layers": { + "1": { + "name": "nodes" + } } }, + "cyclestreets": { + "layers": { + "0": { + "name": "Carrers ciclistes" + }, + "1": { + "name": "Futur carrer ciclista", + "title": { + "render": "Futur carrer ciclista" + } + }, + "2": { + "name": "Tots els carrers", + "title": { + "render": "Carrer" + } + } + }, + "shortDescription": "Un mapa de carrers ciclistes", + "title": "Carrers ciclistes" + }, + "drinking_water": { + "title": "Aigua potable" + }, + "entrances": { + "title": "Entrades" + }, + "etymology": { + "title": "Open Etymology Map" + }, + "facadegardens": { + "layers": { + "0": { + "description": "Jardins verticals", + "name": "Jardins verticals", + "presets": { + "0": { + "description": "Afegeix un jardí vertical", + "title": "un jardí vertical" + } + }, + "title": { + "render": "Jardí vertical" + } + } + }, + "title": "Jardins verticals" + }, + "food": { + "title": "Restaurants i menjar ràpid" + }, + "fritures": { + "layers": { + "0": { + "override": { + "name": "Botigues de patates" + } + } + }, + "title": "Botigues de patates" + }, + "maps": { + "title": "Un mapa de mapes" + }, + "nature": { + "title": "A la natura" + }, + "notes": { + "title": "Notes a OpenStreetMap" + }, + "observation_towers": { + "title": "Torres d'observació" + }, + "openwindpowermap": { + "title": "OpenWindPowerMap" + }, "personal": { "description": "Crea una interfície basada en totes les capes disponibles de totes les interfícies", "title": "Interfície personal" + }, + "playgrounds": { + "shortDescription": "Un mapa de parcs infantils", + "title": "Parcs infantils" + }, + "postal_codes": { + "description": "Codis postals", + "layers": { + "0": { + "name": "codis postals" + }, + "2": { + "name": "ajuntaments" + } + }, + "shortDescription": "Codis postals", + "title": "Codis postals" + }, + "postboxes": { + "layers": { + "0": { + "name": "Bústies", + "presets": { + "0": { + "title": "una bústia" + } + }, + "title": { + "render": "Bústia" + } + }, + "1": { + "filter": { + "0": { + "options": { + "0": { + "question": "Actualment obert" + } + } + } + }, + "name": "Oficines de correus", + "presets": { + "0": { + "title": "una oficina de correus" + } + }, + "title": { + "render": "Oficina de correus" + } + } + } + }, + "shops": { + "title": "Open Shop Map" + }, + "sidewalks": { + "description": "Petició experimental", + "layers": { + "0": { + "name": "Voreres", + "title": { + "render": "{name}" + } + } + }, + "shortDescription": "Mapejat de voreres", + "title": "Voreres" + }, + "sport_pitches": { + "title": "Camps d'esports" + }, + "street_lighting": { + "layers": { + "1": { + "name": "Il·luminació de carrers", + "title": { + "render": "Il·luminació del carrer" + } + }, + "2": { + "name": "Tots els carrers", + "title": { + "render": "Carrer" + } + } + }, + "title": "Il·luminació als carrers" + }, + "surveillance": { + "title": "Vigilància sota vigilància" + }, + "toilets": { + "title": "Open Toilet Map" + }, + "trees": { + "description": "Mapeja tots els arbres.", + "shortDescription": "Mapeja tots els arbres", + "title": "Arbres" + }, + "waste": { + "title": "Brossa" + }, + "waste_basket": { + "title": "Papepera" } } \ No newline at end of file diff --git a/langs/themes/da.json b/langs/themes/da.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/langs/themes/da.json @@ -0,0 +1 @@ +{} diff --git a/langs/themes/de.json b/langs/themes/de.json index 933166668..56f22bcfe 100644 --- a/langs/themes/de.json +++ b/langs/themes/de.json @@ -8,7 +8,7 @@ "title": "Freie Kunstwerk-Karte" }, "benches": { - "description": "Diese Karte zeigt alle Sitzbänke, die in OpenStreetMap eingetragen sind: Einzeln stehende Bänke und Bänke, die zu Haltestellen oder Unterständen gehören. Mit einem OpenStreetMap-Account können Sie neue Bänke eintragen oder Detailinformationen existierender Bänke bearbeiten.", + "description": "Diese Karte zeigt alle Sitzbänke, die in OpenStreetMap eingetragen sind: Alleinstehende Bänke und Bänke, die zu Haltestellen oder Unterständen gehören. Mit einem OpenStreetMap-Konto können Sie neue Bänke eintragen oder Details existierender Bänke bearbeiten.", "shortDescription": "Eine Karte aller Sitzbänke", "title": "Sitzbänke" }, @@ -269,196 +269,6 @@ "climbing": { "description": "Eine Karte mit Klettermöglichkeiten wie Kletterhallen, Kletterparks oder Felsen.", "descriptionTail": "

    kletterspots.de wird betrieben von Christian Neumann. Bitte melden Sie sich, wenn Sie Feedback oder Fragen haben.

    Das Projekt nutzt OpenStreetMap Daten und basiert auf der freien Software MapComplete.

    ", - "layers": { - "0": { - "description": "Ein Kletterverein oder -organisation", - "name": "Klettervereine", - "presets": { - "0": { - "description": "Ein Kletterverein", - "title": "eine kletterverein" - }, - "1": { - "description": "Eine Organisation, die sich mit dem Klettern beschäftigt", - "title": "Eine Kletterorganisation" - } - }, - "tagRenderings": { - "climbing_club-name": { - "question": "Wie lautet der Name dieses Vereins oder Organisation?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Kletter-Organisation" - } - }, - "render": "Kletterverein" - } - }, - "1": { - "description": "Eine Kletterhalle", - "name": "Kletterhallen", - "tagRenderings": { - "name": { - "question": "Wie heißt diese Kletterhalle?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Kletterhalle {name}" - } - }, - "render": "Kletterhalle" - } - }, - "2": { - "name": "Kletterrouten", - "presets": { - "0": { - "title": "eine kletterroute" - } - }, - "tagRenderings": { - "Bolts": { - "mappings": { - "0": { - "then": "Auf dieser Kletterroute sind keine Haken vorhanden" - }, - "1": { - "then": "Auf dieser Kletterroute sind keine Haken vorhanden" - } - }, - "question": "Wie viele Haken gibt es auf dieser Kletterroute bevor der Umlenker bzw. Standhaken erreicht ist?", - "render": "Diese Kletterroute hat {climbing:bolts} Haken" - }, - "Difficulty": { - "question": "Wie hoch ist der Schwierigkeitsgrad dieser Kletterroute nach dem französisch/belgischen System?", - "render": "Die Schwierigkeit ist {climbing:grade:french} entsprechend des französisch/belgischen Systems" - }, - "Length": { - "question": "Wie lang ist diese Kletterroute (in Metern)?", - "render": "Diese Route ist {canonical(climbing:length)} lang" - }, - "Name": { - "mappings": { - "0": { - "then": "Diese Kletterroute hat keinen Namen" - } - }, - "question": "Wie heißt diese Kletterroute?", - "render": "{name}" - }, - "Rock type": { - "render": "Der Gesteinstyp ist {_embedding_features_with_rock:rock}, wie auf dem umgebenden Felsen angegeben" - } - }, - "title": { - "mappings": { - "0": { - "then": "Kleterroute {name}" - } - }, - "render": "Kleterroute" - } - }, - "3": { - "description": "Eine Klettergelegenheit", - "name": "Klettermöglichkeiten", - "presets": { - "0": { - "description": "Eine Klettergelegenheit", - "title": "eine klettermöglichkeit" - } - }, - "tagRenderings": { - "Contained routes hist": { - "render": "

    Schwierigkeitsübersicht

    {histogram(_difficulty_hist)}" - }, - "Contained routes length hist": { - "render": "

    Längenübersicht

    {histogram(_length_hist)}" - }, - "Contained_climbing_routes": { - "render": "

    Enthält {_contained_climbing_routes_count} Routen

      {_contained_climbing_routes}
    " - }, - "Rock type (crag/rock/cliff only)": { - "mappings": { - "0": { - "then": "Kalkstein" - } - }, - "question": "Welchen Gesteinstyp gibt es hier?", - "render": "Der Gesteinstyp ist {rock}" - }, - "Type": { - "mappings": { - "0": { - "then": "Ein Kletterfelsen - ein einzelner Felsen oder eine Klippe mit einer oder wenigen Kletterrouten, die ohne Seil sicher bestiegen werden können" - }, - "1": { - "then": "Ein Kletterfelsen - ein einzelner Fels oder eine Klippe mit mindestens einigen Kletterrouten" - } - } - }, - "name": { - "mappings": { - "0": { - "then": "Diese Klettergelegenheit hat keinen Namen" - } - }, - "question": "Wie heißt diese Klettergelegenheit?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Klettergarten {name}" - }, - "1": { - "then": "Klettergebiet {name}" - }, - "2": { - "then": "Klettergebiet" - }, - "3": { - "then": "Klettermöglichkeit {name}" - } - }, - "render": "Klettermöglichkeit" - } - }, - "4": { - "description": "Eine Klettergelegenheit?", - "name": "Klettermöglichkeiten?", - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - }, - "climbing-possible": { - "mappings": { - "0": { - "then": "Hier kann geklettert werden" - }, - "1": { - "then": "Hier kann nicht geklettert werden" - }, - "2": { - "then": "Hier kann nicht geklettert werden" - } - }, - "question": "Kann hier geklettert werden?" - } - }, - "title": { - "render": "Klettermöglichkeit?" - } - } - }, "overrideAll": { "tagRenderings+": { "0": { @@ -867,7 +677,7 @@ "title": "Pommes-frites-Läden" }, "ghostbikes": { - "description": "Ein Geisterrad ist ein weißes Fahrrad, dass zum Gedenken eines tödlich verunglückten Radfahrers vor Ort aufgestellt wurde.

    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.", + "description": "Ein Geisterrad ist ein weißes Fahrrad, dass zum Gedenken eines tödlich verunglückten Radfahrers vor Ort aufgestellt wurde.

    Auf dieser Karte sehen Sie alle Geisterräder, die in OpenStreetMap eingetragen sind. Fehlt ein Geisterrad? Jeder kann hier Informationen hinzufügen oder aktualisieren - Sie benötigen nur ein (kostenloses) OpenStreetMap-Konto.", "title": "Geisterräder" }, "grb": { @@ -906,71 +716,6 @@ }, "hackerspaces": { "description": "Auf dieser Karte können Sie Hackerspaces sehen, einen neuen Hackerspace hinzufügen oder Daten direkt aktualisieren", - "layers": { - "0": { - "description": "Hackerspace", - "name": "Hackerspaces", - "presets": { - "0": { - "description": "Ein Hackerspace ist ein Ort, an dem sich Menschen treffen, die sich für Software interessieren", - "title": "eine hackerspace" - }, - "1": { - "description": "Ein Makerspace ist ein Ort, an dem Heimwerker-Enthusiasten zusammenkommen, um mit Elektronik zu experimentieren, wie Arduino, LED-Strips, ...", - "title": "eine makerspace" - } - }, - "tagRenderings": { - "hackerspaces-name": { - "question": "Wie lautet der Name dieses Hackerspace?", - "render": "Dieser Hackerspace heißt {name}" - }, - "hackerspaces-opening_hours": { - "mappings": { - "0": { - "then": "durchgehend geöffnet" - } - }, - "question": "Wann hat dieser Hackerspace geöffnet?", - "render": "{opening_hours_table()}" - }, - "hackerspaces-start_date": { - "question": "Wann wurde dieser Hackerspace gegründet?", - "render": "Dieser Hackerspace wurde gegründet am {start_date}" - }, - "hs-club-mate": { - "mappings": { - "0": { - "then": "In diesem Hackerspace gibt es Club Mate" - }, - "1": { - "then": "In diesem Hackerspace gibt es kein Club Mate" - } - }, - "question": "Gibt es in diesem Hackerspace Club Mate?" - }, - "is_makerspace": { - "mappings": { - "0": { - "then": "Dies ist ein Makerspace" - }, - "1": { - "then": "Dies ist ein traditioneller (softwareorientierter) Hackerspace" - } - }, - "question": "Ist dies ein Hackerspace oder ein Makerspace?" - } - }, - "title": { - "mappings": { - "0": { - "then": " {name}" - } - }, - "render": "Hackerspace" - } - } - }, "shortDescription": "Eine Karte von Hackerspaces", "title": "Hackerspaces" }, @@ -1007,6 +752,7 @@ } } }, + "name": "Schwerpunkte von Änderungssätzen", "tagRenderings": { "contributor": { "render": "Änderung wurde von {_last_edit:contributor} gemacht" @@ -1015,18 +761,17 @@ "render": "Änderung {id}" }, "theme": { - "render": "Änderung mit Thema {theme}", "mappings": { "0": { "then": "Änderung mit inoffiziellem Thema {theme}" } - } + }, + "render": "Änderung mit Thema {theme}" } }, "title": { "render": "Änderungen für {theme}" - }, - "name": "Schwerpunkte von Änderungssätzen" + } }, "1": { "override": { @@ -1052,7 +797,7 @@ "title": "In die Natur" }, "notes": { - "description": "Ein Hinweis ist eine Stecknadel auf der Karte mit einer Fehlerbeschreibung.

    Über die Filteransicht kann nach Benutzern und Text gesucht werden.", + "description": "Eine Notiz ist eine Stecknadel auf der Karte mit einer Fehlerbeschreibung.

    Über die Filteransicht kann nach Benutzer und Text gesucht werden.", "title": "Notizen von OpenStreetMap" }, "observation_towers": { @@ -1062,71 +807,6 @@ }, "openwindpowermap": { "description": "Eine Karte zum Anzeigen und Bearbeiten von Windkraftanlagen.", - "layers": { - "0": { - "name": "Windräder", - "presets": { - "0": { - "title": "ein Windrad" - } - }, - "tagRenderings": { - "turbine-diameter": { - "question": "Wie groß ist der Rotordurchmesser der Windturbine in Meter?", - "render": "Der Rotordurchmesser der Windturbine ist {rotor:diameter} Meter." - }, - "turbine-operator": { - "question": "Wer betreibt das Windrads?", - "render": "Die Windturbine wird betrieben von {operator}." - }, - "turbine-output": { - "question": "Wieviel Strom erzeugt das Windrad? (z.B. 2.3MW)", - "render": "Das Windrad erzeugt {generator:output:electricity} Strom." - }, - "turbine-start-date": { - "question": "Wann wurde das Windrad in Betrieb genommen?", - "render": "Das Windrad wurde am {start_date} in Betrieb genommen." - }, - "turbine-height": { - "render": "Die Gesamthöhe dieses Windrads beträgt (einschließlich Rotorradius) {height} Meter.", - "question": "Wie hoch ist dieses Windrad (inklusive Rotorradius) in Metern?" - } - }, - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "Windrad" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " Megawatt" - }, - "1": { - "human": " Kilowatt" - }, - "2": { - "human": " Watt" - }, - "3": { - "human": " Gigawatt" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " Meter" - } - } - } - } - } - }, "title": "Freie Windenergie-Karte" }, "parkings": { @@ -1141,20 +821,20 @@ "playgrounds": { "description": "Auf dieser Karte finden Sie Spielplätze und können weitere Informationen hinzufügen", "shortDescription": "Eine Karte mit Spielplätzen", - "title": "Spielpläzte" + "title": "Spielplätze" }, "postal_codes": { "description": "Postleitzahlen", "layers": { "0": { "name": "Postleitzahlen", - "title": { - "render": "Postleitzahl {postal_code}" - }, "tagRenderings": { "postal_code": { "render": "Die Postleitzahl lautet {postal_code}" } + }, + "title": { + "render": "Postleitzahl {postal_code}" } }, "2": { @@ -1206,8 +886,8 @@ "then": "durchgehend geöffnet (auch an Feiertagen)" } }, - "render": "Öffnungszeiten: {opening_hours_table()}", - "question": "Wie sind die Öffnungszeiten dieser Poststelle?" + "question": "Wie sind die Öffnungszeiten dieser Poststelle?", + "render": "Öffnungszeiten: {opening_hours_table()}" } }, "title": { @@ -1224,23 +904,23 @@ "title": "Freie Geschäftskarte" }, "sidewalks": { + "description": "Experimentelles Thema", "layers": { "0": { + "description": "Ebene mit Bürgersteigen", "name": "Gehweg", - "title": { - "render": "{name}" - }, "tagRenderings": { "streetname": { "render": "Diese Straße heißt {name}" } }, - "description": "Ebene mit Bürgersteigen" + "title": { + "render": "{name}" + } } }, - "title": "Gehwege", - "description": "Experimentelles Thema", - "shortDescription": "Kartierung von Bürgersteigen" + "shortDescription": "Kartierung von Bürgersteigen", + "title": "Gehwege" }, "sport_pitches": { "description": "Ein Sportplatz ist eine Fläche, auf der Sportarten gespielt werden", @@ -1283,14 +963,14 @@ "0": { "then": "Diese Straße ist beleuchtet" }, - "3": { - "then": "Diese Straße ist durchgehend beleuchtet" + "1": { + "then": "Diese Straße ist nicht beleuchtet" }, "2": { "then": "Diese Straße ist nachts beleuchtet" }, - "1": { - "then": "Diese Straße ist nicht beleuchtet" + "3": { + "then": "Diese Straße ist durchgehend beleuchtet" } }, "question": "Ist diese Straße beleuchtet?" @@ -1326,4 +1006,4 @@ "shortDescription": "Eine Karte mit Abfalleimern", "title": "Abfalleimer" } -} +} \ No newline at end of file diff --git a/langs/themes/en.json b/langs/themes/en.json index 80a08d43f..58279b6f6 100644 --- a/langs/themes/en.json +++ b/langs/themes/en.json @@ -269,196 +269,6 @@ "climbing": { "description": "On this map you will find various climbing opportunities such as climbing gyms, bouldering halls and rocks in nature.", "descriptionTail": "The climbing map was originally made by Christian Neumann. Please get in touch if you have feedback or questions.

    The project uses data of the OpenStreetMap project.

    ", - "layers": { - "0": { - "description": "A climbing club or organisation", - "name": "Climbing club", - "presets": { - "0": { - "description": "A climbing club", - "title": "a climbing club" - }, - "1": { - "description": "An NGO working around climbing", - "title": "a climbing ngo" - } - }, - "tagRenderings": { - "climbing_club-name": { - "question": "What is the name of this climbing club or NGO?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Climbing NGO" - } - }, - "render": "Climbing club" - } - }, - "1": { - "description": "A climbing gym", - "name": "Climbing gyms", - "tagRenderings": { - "name": { - "question": "What is the name of this climbing gym?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Climbing gym {name}" - } - }, - "render": "Climbing gym" - } - }, - "2": { - "name": "Climbing routes", - "presets": { - "0": { - "title": "a climbing route" - } - }, - "tagRenderings": { - "Bolts": { - "mappings": { - "0": { - "then": "This route is not bolted" - }, - "1": { - "then": "This route is not bolted" - } - }, - "question": "How many bolts does this route have before reaching the anchor?", - "render": "This route has {climbing:bolts} bolts" - }, - "Difficulty": { - "question": "What is the grade of this climbing route according to the french/belgian system?", - "render": "The grade is {climbing:grade:french} according to the french/belgian system" - }, - "Length": { - "question": "How long is this climbing route (in meters)?", - "render": "This route is {canonical(climbing:length)} long" - }, - "Name": { - "mappings": { - "0": { - "then": "This climbing route doesn't have a name" - } - }, - "question": "What is the name of this climbing route?", - "render": "{name}" - }, - "Rock type": { - "render": "The rock type is {_embedding_features_with_rock:rock} as stated on the surrounding crag" - } - }, - "title": { - "mappings": { - "0": { - "then": "Climbing route {name}" - } - }, - "render": "Climbing route" - } - }, - "3": { - "description": "A climbing opportunity", - "name": "Climbing opportunities", - "presets": { - "0": { - "description": "A climbing opportunity", - "title": "a climbing opportunity" - } - }, - "tagRenderings": { - "Contained routes hist": { - "render": "

    Grades overview

    {histogram(_difficulty_hist)}" - }, - "Contained routes length hist": { - "render": "

    Length overview

    {histogram(_length_hist)}" - }, - "Contained_climbing_routes": { - "render": "

    Contains {_contained_climbing_routes_count} routes

      {_contained_climbing_routes}
    " - }, - "Rock type (crag/rock/cliff only)": { - "mappings": { - "0": { - "then": "Limestone" - } - }, - "question": "What is the rock type here?", - "render": "The rock type is {rock}" - }, - "Type": { - "mappings": { - "0": { - "then": "A climbing boulder - a single rock or cliff with one or a few climbing routes which can be climbed safely without rope" - }, - "1": { - "then": "A climbing crag - a single rock or cliff with at least a few climbing routes" - } - } - }, - "name": { - "mappings": { - "0": { - "then": "This climbing opportunity doesn't have a name" - } - }, - "question": "What is the name of this climbing opportunity?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Climbing crag {name}" - }, - "1": { - "then": "Climbing area {name}" - }, - "2": { - "then": "Climbing site" - }, - "3": { - "then": "Climbing opportunity {name}" - } - }, - "render": "Climbing opportunity" - } - }, - "4": { - "description": "A climbing opportunity?", - "name": "Climbing opportunities?", - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - }, - "climbing-possible": { - "mappings": { - "0": { - "then": "Climbing is possible here" - }, - "1": { - "then": "Climbing is not possible here" - }, - "2": { - "then": "Climbing is not possible here" - } - }, - "question": "Is climbing possible here?" - } - }, - "title": { - "render": "Climbing opportunity?" - } - } - }, "overrideAll": { "tagRenderings+": { "0": { @@ -906,71 +716,6 @@ }, "hackerspaces": { "description": "On this map you can see hackerspaces, add a new hackerspace or update data directly", - "layers": { - "0": { - "description": "Hackerspace", - "name": "Hackerspace", - "presets": { - "0": { - "description": "A hackerspace is an area where people interested in software gather", - "title": "a hackerspace" - }, - "1": { - "description": "A makerspace is a place where DIY-enthusiasts gather to experiment with electronics such as arduino, LEDstrips, ...", - "title": "a makerspace" - } - }, - "tagRenderings": { - "hackerspaces-name": { - "question": "What is the name of this hackerspace?", - "render": "This hackerspace is named {name}" - }, - "hackerspaces-opening_hours": { - "mappings": { - "0": { - "then": "Opened 24/7" - } - }, - "question": "When is this hackerspace opened?", - "render": "{opening_hours_table()}" - }, - "hackerspaces-start_date": { - "question": "When was this hackerspace founded?", - "render": "This hackerspace was founded at {start_date}" - }, - "hs-club-mate": { - "mappings": { - "0": { - "then": "This hackerspace serves club mate" - }, - "1": { - "then": "This hackerspace does not serve club mate" - } - }, - "question": "Does this hackerspace serve Club Mate?" - }, - "is_makerspace": { - "mappings": { - "0": { - "then": "This is a makerspace" - }, - "1": { - "then": "This is a traditional (software oriented) hackerspace" - } - }, - "question": "Is this a hackerspace or a makerspace?" - } - }, - "title": { - "mappings": { - "0": { - "then": " {name}" - } - }, - "render": "Hackerspace" - } - } - }, "shortDescription": "A map of hackerspaces", "title": "Hackerspaces" }, @@ -1062,71 +807,6 @@ }, "openwindpowermap": { "description": "A map for showing and editing wind turbines.", - "layers": { - "0": { - "name": "wind turbine", - "presets": { - "0": { - "title": "a wind turbine" - } - }, - "tagRenderings": { - "turbine-diameter": { - "question": "What is the rotor diameter of this wind turbine, in metres?", - "render": "The rotor diameter of this wind turbine is {rotor:diameter} metres." - }, - "turbine-height": { - "question": "What is the total height of this wind turbine (including rotor radius), in metres?", - "render": "The total height (including rotor radius) of this wind turbine is {height} metres." - }, - "turbine-operator": { - "question": "Who operates this wind turbine?", - "render": "This wind turbine is operated by {operator}." - }, - "turbine-output": { - "question": "What is the power output of this wind turbine? (e.g. 2.3 MW)", - "render": "The power output of this wind turbine is {generator:output:electricity}." - }, - "turbine-start-date": { - "question": "When did this wind turbine go into operation?", - "render": "This wind turbine went into operation on/in {start_date}." - } - }, - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "wind turbine" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " megawatts" - }, - "1": { - "human": " kilowatts" - }, - "2": { - "human": " watts" - }, - "3": { - "human": " gigawatts" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " meter" - } - } - } - } - } - }, "title": "OpenWindPowerMap" }, "parkings": { diff --git a/langs/themes/eo.json b/langs/themes/eo.json index 04e1e7d6f..4912597b3 100644 --- a/langs/themes/eo.json +++ b/langs/themes/eo.json @@ -41,43 +41,5 @@ }, "maps": { "title": "Mapo de mapoj" - }, - "openwindpowermap": { - "layers": { - "0": { - "title": { - "mappings": { - "0": { - "then": "{name}" - } - } - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " megavatoj" - }, - "1": { - "human": " kilovatoj" - }, - "2": { - "human": " vatoj" - }, - "3": { - "human": " gigavatoj" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " metro" - } - } - } - } - } - } } } \ No newline at end of file diff --git a/langs/themes/es.json b/langs/themes/es.json index 8d1534017..b1af01d8a 100644 --- a/langs/themes/es.json +++ b/langs/themes/es.json @@ -6,11 +6,143 @@ "artwork": { "description": "Bienvenido a Open Artwork Map, un mapa de estatuas, bustos, grafitis y otras obras de arte de todo el mundo" }, + "benches": { + "description": "Este mapa muestra todos los bancos que están grabados en OpenStreetMap: Bancos individuales, bancos que pertenecen a paradas o marquesinas del transporte público. Con una cuenta de OpenStreetMap, puedes mapear nuevos bancos o editar detalles de bancos existentes.", + "shortDescription": "Un mapa de bancos", + "title": "Bancos" + }, + "bicycle_rental": { + "description": "En este mapa, encontrarás numerosas estaciones de alquiler de bicicletas que son conocidas por OpenStreetMap", + "shortDescription": "Un mapa con estaciones de alquiler de bicicletas y tiendas de alquiler de bicicletas", + "title": "Alquiler de bicicletas" + }, + "binoculars": { + "description": "Un mapa con prismáticos fijos en un poste. Suele encontrarse en lugares turísticos, miradores, en lo alto de torres panorámicas u ocasionalmente en una reserva natural.", + "shortDescription": "Un mapa con prismáticos fijos", + "title": "Binoculares" + }, + "bookcases": { + "description": "Una librería pública es un pequeño armario en la calle, una caja, una vieja cabina telefónica o algún otro objeto donde se guardan libros. Todo el mundo puede colocar o coger un libro. Este mapa pretende recoger todas estas librerías. Puedes descubrir nuevas librerías cercanas y, con una cuenta gratuita de OpenStreetMap, añadir rápidamente tus librerías favoritas.", + "title": "Mapa de Librerías Abiertas" + }, + "cafes_and_pubs": { + "description": "Pubs y bares", + "title": "Cafeterías y pubs" + }, + "campersite": { + "description": "Este sitio recoge todos los lugares oficiales de parada de caravanas y los lugares donde se pueden verter las aguas grises y negras. Puedes añadir detalles sobre los servicios prestados y el coste. Añade fotos y reseñas. Este es un sitio web y una aplicación web. Los datos se almacenan en OpenStreetMap, por lo que serán gratuitos para siempre y podrán ser reutilizados por cualquier aplicación.", + "layers": { + "0": { + "description": "Sitios de acampada", + "name": "Sitios de Acampada", + "presets": { + "0": { + "description": "Añade un nuevo sitio de acampada oficial. Son lugares designados para pasar la noche con tu caravana. Pueden parecerse a un camping real o simplemente a un aparcamiento. Puede que no estén señalizados en absoluto, sino que simplemente estén definidos en una decisión municipal. Un aparcamiento normal destinado a los campistas en el que no se espera que se pase la noche, no es un camping. ", + "title": "Un camping" + } + }, + "tagRenderings": { + "caravansites-capacity": { + "question": "¿Cuántos campistas pueden alojarse aquí? (omitir si no hay un número evidente de plazas o vehículos permitidos)", + "render": "{capacity} los campistas pueden utilizar este lugar al mismo tiempo" + }, + "caravansites-charge": { + "question": "¿Cuánto cobra este lugar?", + "render": "Este lugar cobra {charge}" + }, + "caravansites-description": { + "question": "¿Te gustaría añadir una descripción general de este lugar? (No repitas información previamente preguntada o mostrada arriba. Por favor mantenla objetiva - las opiniones van en la de opiniones)", + "render": "Más detalles sobre este lugar:{description}" + }, + "caravansites-fee": { + "mappings": { + "0": { + "then": "Necesitas pagar por su uso" + }, + "1": { + "then": "Se puede usar de manera gratuita" + } + }, + "question": "¿Este lugar cobra una tarifa?" + }, + "caravansites-internet": { + "mappings": { + "0": { + "then": "Hay acceso a internet" + }, + "1": { + "then": "Hay acceso a internet" + }, + "2": { + "then": "No hay acceso a internet" + } + }, + "question": "¿Este lugar tiene acceso a internet?" + }, + "caravansites-internet-fee": { + "mappings": { + "0": { + "then": "Tienes que pagar a mayores por el acceso a internet" + }, + "1": { + "then": "No tienes que pagar a mayores por el acceso a internet" + } + }, + "question": "¿Tienes que pagar por el acceso a internet?" + }, + "caravansites-long-term": { + "mappings": { + "0": { + "then": "Sí, hay algunas plazas de alquiler a largo plazo, pero también puedes alojarte por días" + }, + "1": { + "then": "No, no hay huéspedes permanentes aquí" + }, + "2": { + "then": "Solo es posible permanecer aquí si tienes un contrato a largo plazo (este lugar desaparecerá de este mapa si escoges esto)" + } + }, + "question": "¿Este lugar ofrece huecos para alquilar a largo plazo?" + }, + "caravansites-name": { + "question": "¿Cómo se llama este lugar?", + "render": "Este lugar se llama {name}" + }, + "caravansites-sanitary-dump": { + "mappings": { + "0": { + "then": "Este lugar tiene un vertedero sanitario" + }, + "1": { + "then": "Este lugar no tiene vertedero sanitario" + } + }, + "question": "¿Este lugar tiene un vertedero sanitario?" + }, + "caravansites-toilets": { + "mappings": { + "0": { + "then": "Este lugar cuenta con sanitarios" + }, + "1": { + "then": "Este lugar no tiene sanitarios" + } + } + } + } + } + } + }, "ghostbikes": { "title": "Bicicleta blanca" }, "personal": { "description": "Crea una interficie basada en todas las capas disponibles de todas las interficies", "title": "Interficie personal" + }, + "trees": { + "description": "Mapa de todos los Árboles", + "shortDescription": "Mapa de los Árboles", + "title": "Árboles" } } \ No newline at end of file diff --git a/langs/themes/fr.json b/langs/themes/fr.json index aa6d33211..eeb226c08 100644 --- a/langs/themes/fr.json +++ b/langs/themes/fr.json @@ -21,10 +21,19 @@ "description": "Une vélothèque est un endroit où on peut emprunter des vélos, souvent moyennant une petite somme annuelle. Un cas d'utilisation notable est celui des vélothèques pour les enfants, qui leur permettent de passer à un vélo plus grand quand ils sont trop grands pour leur vélo actuel", "title": "Vélothèques" }, + "binoculars": { + "description": "Une carte des longue-vues fixes. Se trouve typiquement sur les sites touristiques, les points de vue, les tours panoramiques ou dans les réserves naturelles.", + "shortDescription": "Une carte de jumelles panoramiques", + "title": "Jumelles" + }, "bookcases": { "description": "Une microbibliothèques, également appelée boite à livre, est un élément de mobilier urbain (étagère, armoire, etc) dans lequel sont stockés des livres et autres objets en accès libre. Découvrez les boites à livres prêt de chez vous, ou ajouter en une nouvelle à l'aide de votre compte OpenStreetMap.", "title": "Carte des microbibliothèques" }, + "cafes_and_pubs": { + "description": "Bars et pubs", + "title": "Cafés et pubs" + }, "campersite": { "description": "Ce site collecte les zones de camping officielles ainsi que les aires de vidange. Il est possible d’ajouter des détails à propos des services proposés ainsi que leurs coûts. Ajoutez vos images et avis. C’est un site et une application. Les données sont stockées sur OpenStreetMap, elles seront toujours gratuites et peuvent être réutilisées par n’importe quelle application.", "layers": { @@ -252,199 +261,14 @@ "shortDescription": "Trouver des sites pour passer la nuit avec votre camping-car", "title": "Sites pour camping-cars" }, + "charging_stations": { + "description": "Sur cette carte l’on trouve et ajoute des informations sur les points de recharge", + "shortDescription": "Une carte mondiale des points de recharge", + "title": "Points de recharge" + }, "climbing": { "description": "Cette carte indique les sites d’escalades comme les salles d’escalade ou les sites naturels.", "descriptionTail": "La carte des sites d'escalade a été créée par Christian Neumann. Merci de le contacter pour des avis ou des questions.

    Ce projet utilise les données OpenStreetMap.

    ", - "layers": { - "0": { - "description": "Club ou association d’escalade", - "name": "Club d’escalade", - "presets": { - "0": { - "description": "Un club d’escalade", - "title": "une club d’escalade" - }, - "1": { - "description": "Une association d’escalade", - "title": "une association d’escalade" - } - }, - "tagRenderings": { - "climbing_club-name": { - "question": "Quel est le nom du club ou de l’association ?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Association d’escalade" - } - }, - "render": "Club d’escalade" - } - }, - "1": { - "description": "Une salle d’escalade", - "name": "Salle d’escalade", - "tagRenderings": { - "name": { - "question": "Quel est le nom de la salle d’escalade ?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Salle d’escalade {name}" - } - }, - "render": "Salle d’escalade" - } - }, - "2": { - "name": "Voies d’escalade", - "presets": { - "0": { - "title": "une voie d’escalade" - } - }, - "tagRenderings": { - "Bolts": { - "mappings": { - "0": { - "then": "Cette voie n’a pas de prises" - }, - "1": { - "then": "Cette voie n’a pas de prises" - } - }, - "question": "Combien de prises cette voie possède avant d’atteindre la moulinette ?", - "render": "Cette voie a {climbing:bolts} prises" - }, - "Difficulty": { - "question": "Quelle est la difficulté de cette voie selon le système franco-belge ?", - "render": "Selon le système franco-belge, la difficulté de cette voie est de {climbing:grade:french}" - }, - "Length": { - "question": "Quelle est la longueur de cette voie (en mètres) ?", - "render": "Cette voie fait {canonical(climbing:length)} de long" - }, - "Name": { - "mappings": { - "0": { - "then": "Cette voie n’a pas de nom" - } - }, - "question": "Quel est le nom de cette voie d’escalade ?", - "render": "{name}" - }, - "Rock type": { - "render": "Le type de roche est {_embedding_features_with_rock:rock} selon le mur" - } - }, - "title": { - "mappings": { - "0": { - "then": "Voie d’escalade {name}" - } - }, - "render": "Voie d’escalade" - } - }, - "3": { - "description": "Opportunité d’escalade", - "name": "Opportunité d’escalade", - "presets": { - "0": { - "description": "Opportunité d’escalade", - "title": "une opportunité d’escalade" - } - }, - "tagRenderings": { - "Contained routes hist": { - "render": "

    Résumé des difficultés

    {histogram(_difficulty_hist)}" - }, - "Contained routes length hist": { - "render": "

    Résumé de longueur

    {histogram(_length_hist)}" - }, - "Contained_climbing_routes": { - "render": "

    Contient {_contained_climbing_routes_count} voies

      {_contained_climbing_routes}
    " - }, - "Rock type (crag/rock/cliff only)": { - "mappings": { - "0": { - "then": "Calcaire" - } - }, - "question": "Quel est le type de roche ?", - "render": "La roche est du {rock}" - }, - "Type": { - "mappings": { - "0": { - "then": "Rocher d’escalade, rocher avec une ou peu de voie permettant d’escalader sans corde" - }, - "1": { - "then": "Mur d’escalade, rocher avec plusieurs voies d’escalades" - } - } - }, - "name": { - "mappings": { - "0": { - "then": "Ce site n’a pas de nom" - } - }, - "question": "Quel est le nom de ce site ?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Mur d’escalade {name}" - }, - "1": { - "then": "Zone d’escalade {name}" - }, - "2": { - "then": "Site d’escalade" - }, - "3": { - "then": "Opportunité d’escalade {name}" - } - }, - "render": "Opportunité d’escalade" - } - }, - "4": { - "description": "Opportunité d’escalade ?", - "name": "Opportunités d’escalade ?", - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - }, - "climbing-possible": { - "mappings": { - "0": { - "then": "Escalader est possible" - }, - "1": { - "then": "Escalader n’est pas possible" - }, - "2": { - "then": "Escalader n’est pas possible" - } - }, - "question": "Est-il possible d’escalader ici ?" - } - }, - "title": { - "render": "Opportunité d’escalade ?" - } - } - }, "overrideAll": { "tagRenderings+": { "0": { @@ -525,6 +349,16 @@ } }, "question": "Est-il possible d’escalader à la moulinette ?" + }, + "9": { + "mappings": { + "0": { + "then": "De l’escalade est possible ici" + }, + "1": { + "then": "L’escalade est impossible ici" + } + } } }, "units+": { @@ -542,6 +376,21 @@ }, "title": "Open Climbing Map" }, + "cycle_highways": { + "description": "Cette carte affiche les aménagements cyclables", + "layers": { + "0": { + "name": "Aménagements cyclables", + "title": { + "render": "Aménagement cyclable" + } + } + }, + "title": "Aménagements cyclables" + }, + "cycle_infra": { + "description": "Une carte montrant les aménagements cyclables et où l’on peut rajouter des informations. Réalisée durant #osoc21." + }, "cyclofix": { "description": "Le but de cette carte est de présenter aux cyclistes une solution facile à utiliser pour trouver l'infrastructure appropriée à leurs besoins.

    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.

    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.

    Pour plus d'informations sur le projet cyclofix, rendez-vous sur cyclofix.osm.be.", "title": "Cyclofix - Une carte ouverte pour les cyclistes" @@ -704,73 +553,12 @@ }, "openwindpowermap": { "description": "Une carte indiquant les éoliennes et permettant leur édition.", - "layers": { - "0": { - "name": "Éolienne", - "presets": { - "0": { - "title": "une éolienne" - } - }, - "tagRenderings": { - "turbine-diameter": { - "question": "Quel est le diamètre du rotor en mètres ?", - "render": "Le diamètre du rotor est de {rotor:diameter} mètres." - }, - "turbine-height": { - "question": "Quelle est la hauteur totale de l’éolienne en mètres, pales incluses ?", - "render": "La hauteur totale, incluant les pales, est de {height} mètres." - }, - "turbine-operator": { - "question": "Qui est l’exploitant de cette éolienne ?", - "render": "Cette éolienne est opérée par {operator}." - }, - "turbine-output": { - "question": "Quel est la puissance générée par cette éolienne ?", - "render": "La puissance générée par cette éolienne est de {generator:output:electricity}." - }, - "turbine-start-date": { - "question": "Depuis quand l’éolienne est-elle en fonctionnement ?", - "render": "L’éolienne est active depuis {start_date}." - } - }, - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "éolienne" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " megawatts" - }, - "1": { - "human": " kilowatts" - }, - "2": { - "human": " watts" - }, - "3": { - "human": " gigawatts" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " mètres" - } - } - } - } - } - }, "title": "OpenWindPowerMap" }, + "parkings": { + "description": "Cette carte affiche différents lieux de stationnement", + "title": "Stationnement" + }, "personal": { "description": "Crée un thème personnalisé basé sur toutes les couches disponibles de tous les thèmes", "title": "Thème personnalisé" diff --git a/langs/themes/hu.json b/langs/themes/hu.json index 67e3d2e82..c7e3fc42d 100644 --- a/langs/themes/hu.json +++ b/langs/themes/hu.json @@ -93,35 +93,6 @@ "climbing": { "description": "Ezen a térképen különböző mászási lehetőségeket talál, például falmászótermeket, bouldertermeket és sziklákat a természetben.", "descriptionTail": "A mászótérképet eredetileg Christian Neumann készítette. Ha észrevétele vagy kérdése van, kérjük, vele lépjen kapcsolatba.

    A projekt az OpenStreetMap adatait használja

    ", - "layers": { - "0": { - "description": "Mászóegyesület vagy -szervezet", - "name": "Mászóegyesület", - "presets": { - "0": { - "description": "Egy mászóegyesület", - "title": "Mászóegyesület" - }, - "1": { - "description": "Mászással foglalkozó civil szervezet", - "title": "Mászószervezet" - } - }, - "tagRenderings": { - "climbing_club-name": { - "question": "Mi a neve ennek a mászóegyesületnek vagy szervezetnek?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Mászószervezet" - } - } - } - } - }, "overrideAll": { "tagRenderings+": { "9": { @@ -336,43 +307,6 @@ }, "hackerspaces": { "description": "Ezen a térképen hackerspace-ek láthatók, új hackerspace-eket lehet fölrajzolni vagy meglévők adatait frissíteni", - "layers": { - "0": { - "description": "Hackerspace", - "name": "Hackerspace", - "presets": { - "0": { - "description": "A hackerspace egy olyan hely, ahol szoftverek iránt érdeklő emberek találkoznak", - "title": "Hackerspace" - }, - "1": { - "description": "A makerspace olyan hely, ahol a barkácsolás szerelmesei találkoznak, hogy olyan elektronikai eszközökkel kísérletezzenek, mint például az Arduino vagy a LEDstrips.", - "title": "Makerspace" - } - }, - "tagRenderings": { - "is_makerspace": { - "mappings": { - "0": { - "then": "Ez egy makerspace" - }, - "1": { - "then": "Ez egy hagyományos (szoftverekkel foglalkozó) hackerspace" - } - }, - "question": "Ez hackerspace vagy makerspace?" - } - }, - "title": { - "mappings": { - "0": { - "then": " {name}" - } - }, - "render": "Hackerspace" - } - } - }, "shortDescription": "Hackerspace-ek térképe", "title": "Hackerspace-ek" }, @@ -392,66 +326,6 @@ }, "openwindpowermap": { "description": "Szélerőművek megjelenítésére és szerkesztésére szolgáló térkép.", - "layers": { - "0": { - "name": "Szélerőmű", - "presets": { - "0": { - "title": "Szélerőmű" - } - }, - "tagRenderings": { - "turbine-diameter": { - "question": "Hány méter a rotorátmérője ennek a szélturbinának?", - "render": "A szélturbina rotorátmérője: {rotor:diameter} méter." - }, - "turbine-height": { - "question": "Hány méter a szélerőmű teljes magassága (a rotor sugarával együtt)?", - "render": "A szélerőmű teljes (rotor sugarával együtt számított) magassága: {height} méter." - }, - "turbine-operator": { - "question": "Ki üzemelteti ezt a szélturbinát?", - "render": "Ennek a szélerőműnek az üzemeltetője: {operator}." - }, - "turbine-output": { - "question": "Mekkora a teljesítménye ennek a szélturbinának? (pl. 2.3 MW)", - "render": "A szélerőmű teljesítménye: {generator:output:electricity}." - }, - "turbine-start-date": { - "question": "Mikor helyezték üzembe ezt a szélerőművet?", - "render": "A szélerőmű üzembe helyezése: {start_date}." - } - }, - "title": { - "render": "szélerőmű" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " megawatt" - }, - "1": { - "human": " kilowatt" - }, - "2": { - "human": " watt" - }, - "3": { - "human": " gigawatt" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " méter" - } - } - } - } - } - }, "title": "OpenWindPowerMap" }, "parkings": { diff --git a/langs/themes/id.json b/langs/themes/id.json index f78f2a16e..addb20850 100644 --- a/langs/themes/id.json +++ b/langs/themes/id.json @@ -108,96 +108,7 @@ "charging_stations": { "title": "Stasiun pengisian daya" }, - "climbing": { - "layers": { - "0": { - "tagRenderings": { - "climbing_club-name": { - "render": "{name}" - } - } - }, - "1": { - "tagRenderings": { - "name": { - "render": "{name}" - } - } - }, - "2": { - "tagRenderings": { - "Name": { - "render": "{name}" - } - } - }, - "3": { - "tagRenderings": { - "name": { - "render": "{name}" - } - } - }, - "4": { - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - } - } - } - } - }, "openwindpowermap": { - "layers": { - "0": { - "tagRenderings": { - "turbine-operator": { - "render": "Turbin angin ini dioperasikan oleh {operator}." - }, - "turbine-output": { - "question": "Berapa output daya dari turbin angin ini? (misalnya 2,3 MW)", - "render": "Output daya dari turbin angin ini adalah {generator:output:electricity}." - }, - "turbine-start-date": { - "question": "Kapan turbin angin ini mulai beroperasi?", - "render": "Turbin angin ini mulai beroperasi pada/dalam {start_date}." - } - }, - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "turbin angin" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " megawat" - }, - "1": { - "human": " kilowat" - }, - "2": { - "human": " watt" - }, - "3": { - "human": " gigawatt" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " meter" - } - } - } - } - } - }, "title": "OpenWindPowerMap" }, "parkings": { diff --git a/langs/themes/it.json b/langs/themes/it.json index c1bd03d8e..b39d5b450 100644 --- a/langs/themes/it.json +++ b/langs/themes/it.json @@ -263,196 +263,6 @@ "climbing": { "description": "In questa cartina puoi trovare vari luoghi per arrampicata come ad esempio palestre di arrampicata, sale di pratica e rocce naturali.", "descriptionTail": "La cartina di arrampicata è stata originariamente creata da Christian Neumann. Si prega di scrivere qua se si hanno commenti o domande da fare.

    Il progetto usa i dati del progetto OpenStreetMap.

    ", - "layers": { - "0": { - "description": "Un club o associazione di arrampacata", - "name": "Club di arrampicata", - "presets": { - "0": { - "description": "Un club di arrampicata", - "title": "una club di arrampicata" - }, - "1": { - "description": "Un’associazione che ha a che fare con l’arrampicata", - "title": "una associazione di arrampicata" - } - }, - "tagRenderings": { - "climbing_club-name": { - "question": "Qual è il nome di questo club o associazione di arrampicata?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Associazione di arrampicata" - } - }, - "render": "Club di arrampicata" - } - }, - "1": { - "description": "Una palestra di arrampicata", - "name": "Palestre di arrampicata", - "tagRenderings": { - "name": { - "question": "Qual è il nome di questa palestra di arrampicata?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Palestra di arrampicata {name}" - } - }, - "render": "Palestra di arrampicata" - } - }, - "2": { - "name": "Vie di arrampicata", - "presets": { - "0": { - "title": "una via di arrampicata" - } - }, - "tagRenderings": { - "Bolts": { - "mappings": { - "0": { - "then": "In questo percorso non sono presenti bulloni" - }, - "1": { - "then": "In questo percorso non sono presenti bulloni" - } - }, - "question": "Quanti bulloni sono presenti in questo percorso prima di arrivare alla moulinette?", - "render": "Questo percorso ha {climbing:bolts} bulloni" - }, - "Difficulty": { - "question": "Qual è la difficoltà di questa via di arrampicata nel sistema francese/belga?", - "render": "Il grado di difficoltà è {climbing:grade:french} nel sistema francese/belga" - }, - "Length": { - "question": "Quanto è lunga questa via di arrampicata (in metri)?", - "render": "Questo percorso è lungo {canonical(climbing:length)}" - }, - "Name": { - "mappings": { - "0": { - "then": "Questa via di arrampicata non ha un nome" - } - }, - "question": "Come si chiama questa via di arrampicata?", - "render": "{name}" - }, - "Rock type": { - "render": "Il tipo di roccia è {_embedding_features_with_rock:rock} come dichiarato sul muro circostante" - } - }, - "title": { - "mappings": { - "0": { - "then": "Via di arrampicata {name}" - } - }, - "render": "Via di arrampicata" - } - }, - "3": { - "description": "Un’opportunità di arrampicata", - "name": "Opportunità di arrampicata", - "presets": { - "0": { - "description": "Un’opportunità di arrampicata", - "title": "una opportunità di arrampicata" - } - }, - "tagRenderings": { - "Contained routes hist": { - "render": "

    Riassunto delle difficoltà

    {histogram(_difficulty_hist)}" - }, - "Contained routes length hist": { - "render": "

    Riassunto della lunghezza

    {histogram(_length_hist)}" - }, - "Contained_climbing_routes": { - "render": "

    Contiene {_contained_climbing_routes_count} vie

      {_contained_climbing_routes}
    " - }, - "Rock type (crag/rock/cliff only)": { - "mappings": { - "0": { - "then": "Calcare" - } - }, - "question": "Qual è il tipo di roccia qua?", - "render": "Il tipo di roccia è {rock}" - }, - "Type": { - "mappings": { - "0": { - "then": "Un masso per arrampicata (una singola roccia o falesia con una o poche vie di arrampicata che possono essere scalate in sicurezza senza una corda)" - }, - "1": { - "then": "Un muro da arrampicata (un singolo masso o falesia con almeno qualche via per arrampicata)" - } - } - }, - "name": { - "mappings": { - "0": { - "then": "Questa opportunità di arrampicata non ha un nome" - } - }, - "question": "Qual è il nome di questa opportunità di arrampicata?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Muro da arrampicata {name}" - }, - "1": { - "then": "Area di arrampicata {name}" - }, - "2": { - "then": "Sito di arrampicata" - }, - "3": { - "then": "Opportunità di arrampicata {name}" - } - }, - "render": "Opportunità di arrampicata" - } - }, - "4": { - "description": "Un’opportunità di arrampicata?", - "name": "Opportunità di arrampicata?", - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - }, - "climbing-possible": { - "mappings": { - "0": { - "then": "È possibile arrampicarsi qua" - }, - "1": { - "then": "Non è possibile arrampicarsi qua" - }, - "2": { - "then": "Non è possibile arrampicarsi qua" - } - }, - "question": "È possibile arrampicarsi qua?" - } - }, - "title": { - "render": "Opportunità di arrampicata?" - } - } - }, "overrideAll": { "tagRenderings+": { "0": { @@ -806,71 +616,6 @@ }, "openwindpowermap": { "description": "Una cartina per la visione e la modifica delle turbine eoliche.", - "layers": { - "0": { - "name": "pala eolica", - "presets": { - "0": { - "title": "una pala eolica" - } - }, - "tagRenderings": { - "turbine-diameter": { - "question": "Qual è il diametro (in metri) del rotore di questa pala eolica?", - "render": "Il diametro del rotore di questa pala eolica è di {rotor:diameter} metri." - }, - "turbine-height": { - "question": "Qual è l’altezza (in metri e raggio del rotore incluso) di questa pala eolica?", - "render": "L’altezza totale (raggio del rotore incluso) di questa pala eolica è di {height} metri." - }, - "turbine-operator": { - "question": "Chi gestisce questa pala eolica?", - "render": "Questa pala eolica è gestita da {operator}." - }, - "turbine-output": { - "question": "Quant’è la potenza generata da questa pala eolica? (ad es. 2.3 MW)", - "render": "La potenza generata da questa pala eolica è {generator:output:electricity}." - }, - "turbine-start-date": { - "question": "Quando è entrata in funzione questa pala eolica?", - "render": "Questa pala eolica è entrata in funzione in data {start_date}." - } - }, - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "pala eolica" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " megawatt" - }, - "1": { - "human": " kilowatt" - }, - "2": { - "human": " watt" - }, - "3": { - "human": " gigawatt" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " metri" - } - } - } - } - } - }, "title": "OpenWindPowerMap" }, "parkings": { diff --git a/langs/themes/ja.json b/langs/themes/ja.json index f0a7a60c0..35b0d41ef 100644 --- a/langs/themes/ja.json +++ b/langs/themes/ja.json @@ -255,132 +255,6 @@ "climbing": { "description": "この地図には、自然の中のクライミングジム、ボルダリングホール、岩など、さまざまなクライミングの機会があります。", "descriptionTail": "登山地図はもともと Christian Neumann によって作成されたものです。フィードバックや質問がありましたら、ご連絡ください。

    このプロジェクトでは、OpenStreetMapプロジェクトのデータを使用します。

    ", - "layers": { - "0": { - "description": "クライミングクラブや団体", - "name": "クライミングクラブ", - "presets": { - "0": { - "description": "クライミングクラブ", - "title": "クライミングクラブ" - }, - "1": { - "description": "登山に関わるNGO", - "title": "クライミングNGO" - } - }, - "tagRenderings": { - "climbing_club-name": { - "question": "この登山クラブやNGOの名前は何ですか?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "クライミングNGO" - } - }, - "render": "クライミングクラブ" - } - }, - "1": { - "description": "クライミングジム", - "name": "クライミングジム", - "tagRenderings": { - "name": { - "question": "このクライミングジムは何という名前ですか?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "クライミングジム{name}" - } - }, - "render": "クライミングジム" - } - }, - "2": { - "name": "登坂ルート", - "tagRenderings": { - "Difficulty": { - "render": "フランス/ベルギーのランク評価システムによると、{climbing:grade:french}の困難度です" - }, - "Length": { - "render": "このルート長は、 {canonical(climbing:length)} メーターです" - }, - "Name": { - "mappings": { - "0": { - "then": "この登坂ルートには名前がありません" - } - }, - "question": "この登坂ルートの名前は何ですか?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "登坂ルート{name}" - } - }, - "render": "登坂ルート" - } - }, - "3": { - "description": "登坂教室", - "name": "登坂教室", - "presets": { - "0": { - "description": "登坂教室", - "title": "登坂教室" - } - }, - "tagRenderings": { - "name": { - "mappings": { - "0": { - "then": "この登坂教室には名前がついていない" - } - }, - "question": "この登坂教室の名前は何ですか?", - "render": "{name}" - } - }, - "title": { - "render": "登坂教室" - } - }, - "4": { - "description": "登坂教室?", - "name": "登坂教室?", - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - }, - "climbing-possible": { - "mappings": { - "0": { - "then": "ここでは登ることができる" - }, - "1": { - "then": "ここでは登ることができない" - }, - "2": { - "then": "ここでは登ることができない" - } - }, - "question": "ここで登坂はできますか?" - } - }, - "title": { - "render": "登坂教室?" - } - } - }, "overrideAll": { "tagRenderings+": { "0": { diff --git a/langs/themes/nb_NO.json b/langs/themes/nb_NO.json index 57c11dd8a..12fd79fcc 100644 --- a/langs/themes/nb_NO.json +++ b/langs/themes/nb_NO.json @@ -11,6 +11,9 @@ "shortDescription": "Et benkekart", "title": "Benker" }, + "bicycle_rental": { + "title": "Sykkelutleie" + }, "bicyclelib": { "title": "Sykkelbibliotek" }, @@ -66,77 +69,6 @@ "title": "Ladestasjoner" }, "climbing": { - "layers": { - "0": { - "description": "En klatreklubb eller organisasjoner", - "name": "Klatreklubb", - "presets": { - "0": { - "description": "En klatreklubb", - "title": "en klatreklubb" - } - }, - "title": { - "render": "Klatreklubb" - } - }, - "2": { - "name": "Klatreruter", - "tagRenderings": { - "Length": { - "question": "Hvor mange meter er klatreruten?", - "render": "Denne ruten er {canonical(climbing:length)} lang" - }, - "Name": { - "mappings": { - "0": { - "then": "Denne klatreruten har ikke noe navn" - } - }, - "question": "Hva er navnet på denne klatreruten?", - "render": "{name}" - } - }, - "title": { - "render": "Klatrerute" - } - }, - "3": { - "description": "En klatremulighet", - "presets": { - "0": { - "description": "En klatremulighet", - "title": "en klatremulighet" - } - }, - "title": { - "render": "Klatremulighet" - } - }, - "4": { - "description": "En klatremulighet?", - "name": "Klatremuligheter?", - "tagRenderings": { - "climbing-possible": { - "mappings": { - "0": { - "then": "Klatring er mulig her" - }, - "1": { - "then": "Klatring er ikke mulig her" - }, - "2": { - "then": "Klatring er ikke mulig her" - } - }, - "question": "Er klatring mulig her?" - } - }, - "title": { - "render": "Klatremulighet?" - } - } - }, "overrideAll": { "tagRenderings+": { "7": { @@ -240,21 +172,6 @@ "maps": { "title": "Et kart over kart" }, - "openwindpowermap": { - "layers": { - "0": { - "units": { - "0": { - "applicableUnits": { - "1": { - "human": " kilowatt" - } - } - } - } - } - } - }, "parkings": { "shortDescription": "Dette kartet viser forskjellige parkeringsplasser", "title": "Parkering" diff --git a/langs/themes/nl.json b/langs/themes/nl.json index e9dc50f00..deab1b60c 100644 --- a/langs/themes/nl.json +++ b/langs/themes/nl.json @@ -224,6 +224,17 @@ }, "question": "Biedt deze plaats internettoegang?" }, + "caravansites-internet-fee": { + "mappings": { + "0": { + "then": "Je moet extra betalen voor internettoegang" + }, + "1": { + "then": "Je hoeft niet extra te betalen voor internettoegang" + } + }, + "question": "Moet je betalen voor internettoegang?" + }, "caravansites-name": { "question": "Wat is de naam van deze plaats?", "render": "Deze plaats heet {name}" @@ -242,17 +253,6 @@ "caravansites-website": { "question": "Heeft deze plaats een website?", "render": "Officiële website: : {website}" - }, - "caravansites-internet-fee": { - "question": "Moet je betalen voor internettoegang?", - "mappings": { - "0": { - "then": "Je moet extra betalen voor internettoegang" - }, - "1": { - "then": "Je hoeft niet extra te betalen voor internettoegang" - } - } } }, "title": { @@ -275,156 +275,6 @@ "climbing": { "description": "Op deze kaart vind je verschillende klimgelegenheden, zoals klimzalen, bolderzalen en klimmen in de natuur", "descriptionTail": "De klimkaart is oorspronkelijk gemaakt door Christian Neumann op kletterspots.de.", - "layers": { - "0": { - "description": "Een klimclub of organisatie", - "name": "Klimclub", - "presets": { - "0": { - "description": "Een klimclub", - "title": "een klimclub" - }, - "1": { - "description": "Een VZW die werkt rond klimmen", - "title": "een een klimorganisatie" - } - }, - "tagRenderings": { - "climbing_club-name": { - "question": "Wat is de naam van deze klimclub?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Klimorganisatie" - } - }, - "render": "Klimclub" - } - }, - "1": { - "description": "Een klimzaal", - "name": "Klimzalen", - "tagRenderings": { - "name": { - "question": "Wat is de naam van dit Klimzaal?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Klimzaal {name}" - } - }, - "render": "Klimzaal" - } - }, - "2": { - "name": "Klimroute", - "presets": { - "0": { - "title": "een klimroute" - } - }, - "tagRenderings": { - "Difficulty": { - "question": "Hoe moeilijk is deze klimroute volgens het Franse/Belgische systeem?", - "render": "De klimmoeilijkheid is {climbing:grade:french} volgens het Franse/Belgische systeem" - }, - "Length": { - "question": "Hoe lang is deze klimroute (in meters)?", - "render": "Deze klimroute is {canonical(climbing:length)} lang" - }, - "Name": { - "mappings": { - "0": { - "then": "Deze klimroute heeft geen naam" - } - }, - "question": "Hoe heet deze klimroute?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Klimroute {name}" - } - }, - "render": "Klimroute" - } - }, - "3": { - "description": "Een klimgelegenheid", - "name": "Klimgelegenheden", - "presets": { - "0": { - "description": "Een klimgelegenheid", - "title": "een klimgelegenheid" - } - }, - "tagRenderings": { - "Rock type (crag/rock/cliff only)": { - "mappings": { - "0": { - "then": "Kalksteen" - } - } - }, - "name": { - "mappings": { - "0": { - "then": "Dit Klimgelegenheid heeft geen naam" - } - }, - "question": "Wat is de naam van dit Klimgelegenheid?", - "render": "{name}" - } - }, - "title": { - "mappings": { - "1": { - "then": "Klimsite {name}" - }, - "2": { - "then": "Klimsite" - }, - "3": { - "then": "Klimgelegenheid {name}" - } - }, - "render": "Klimgelegenheid" - } - }, - "4": { - "description": "Een klimgelegenheid?", - "name": "Klimgelegenheiden?", - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - }, - "climbing-possible": { - "mappings": { - "0": { - "then": "Klimmen is hier niet toegelaten" - }, - "1": { - "then": "Klimmen is hier niet toegelaten" - }, - "2": { - "then": "Klimmen is hier niet mogelijk" - } - } - } - }, - "title": { - "render": "Klimgelegenheid?" - } - } - }, "overrideAll": { "tagRenderings+": { "0": { @@ -921,44 +771,6 @@ "title": "Uitkijktorens" }, "openwindpowermap": { - "layers": { - "0": { - "name": "windturbine", - "presets": { - "0": { - "title": "een windturbine" - } - }, - "title": { - "render": "windturbine" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " megawatt" - }, - "1": { - "human": " kilowatt" - }, - "2": { - "human": " watt" - }, - "3": { - "human": " gigawatt" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " meter" - } - } - } - } - } - }, "title": "Windmolens" }, "parkings": { @@ -1157,4 +969,4 @@ "shortDescription": "Een kaart met vuilnisbakken", "title": "Vuilnisbak" } -} +} \ No newline at end of file diff --git a/langs/themes/ru.json b/langs/themes/ru.json index 6e5ea55e0..07e2e7290 100644 --- a/langs/themes/ru.json +++ b/langs/themes/ru.json @@ -227,58 +227,6 @@ "climbing": { "description": "На этой карте вы найдете различные возможности для скалолазания, такие как скалодромы, залы для боулдеринга и скалы на природе.", "descriptionTail": "Создатель карты скалолазания — Christian Neumann. Пожалуйста, пишите если у вас есть отзыв или вопросы.

    Проект использует данные OpenStreetMap.

    ", - "layers": { - "0": { - "name": "Клуб скалолазания", - "presets": { - "0": { - "description": "Клуб скалолазания", - "title": "Клуб скалолазания" - } - }, - "tagRenderings": { - "climbing_club-name": { - "render": "{name}" - } - }, - "title": { - "render": "Клуб скалолазания" - } - }, - "1": { - "description": "Комплекс скалолазания", - "name": "Комплексы скалолазания", - "tagRenderings": { - "name": { - "render": "{name}" - } - }, - "title": { - "render": "Комплекс скалолазания" - } - }, - "2": { - "tagRenderings": { - "Name": { - "render": "{name}" - } - } - }, - "3": { - "tagRenderings": { - "name": { - "render": "{name}" - } - } - }, - "4": { - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - } - } - } - }, "overrideAll": { "tagRenderings+": { "0": { @@ -375,35 +323,6 @@ "title": "Велосипед Ghost" }, "hackerspaces": { - "layers": { - "0": { - "description": "Хакерспейс", - "name": "Хакерспейс", - "presets": { - "0": { - "title": "Хакерспейс" - } - }, - "tagRenderings": { - "hackerspaces-opening_hours": { - "mappings": { - "0": { - "then": "Открыто 24/7" - } - }, - "render": "{opening_hours_table()}" - } - }, - "title": { - "mappings": { - "0": { - "then": " {name}" - } - }, - "render": "Хакерспейс" - } - } - }, "title": "Хакерспейсы" }, "hailhydrant": { @@ -418,42 +337,6 @@ "title": "Смотровые башни" }, "openwindpowermap": { - "layers": { - "0": { - "title": { - "mappings": { - "0": { - "then": "{name}" - } - } - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " мегаватт" - }, - "1": { - "human": " киловатт" - }, - "2": { - "human": " ватт" - }, - "3": { - "human": " гигаватт" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " метр" - } - } - } - } - } - }, "title": "Открытая карта ветроэнергетики" }, "parkings": { diff --git a/langs/themes/zh_Hans.json b/langs/themes/zh_Hans.json new file mode 100644 index 000000000..f124b9808 --- /dev/null +++ b/langs/themes/zh_Hans.json @@ -0,0 +1,14 @@ +{ + "aed": { + "description": "在这份地图上可以寻找和标记附近的除颤器", + "title": "Open AED Map" + }, + "artwork": { + "description": "欢迎使用Open Artwork Map,一个雕塑、半身像、涂鸦和其他全球艺术品的地图", + "title": "Open Artwork Map" + }, + "benches": { + "shortDescription": "长椅地图", + "title": "长椅" + } +} \ No newline at end of file diff --git a/langs/themes/zh_Hant.json b/langs/themes/zh_Hant.json index 055ce0e79..a87f75a98 100644 --- a/langs/themes/zh_Hant.json +++ b/langs/themes/zh_Hant.json @@ -252,25 +252,6 @@ "climbing": { "description": "在這份地圖上你會發現能夠攀爬機會,像是攀岩體育館、抱石大廳以及大自然當中的巨石。", "descriptionTail": "攀爬地圖最初由 Christian Neumann 製作。如果你有回饋意見或問題請到Please 這邊反應

    這專案使用來自開放街圖專案的資料。

    ", - "layers": { - "0": { - "description": "攀岩社團或組織", - "name": "攀岩社團", - "tagRenderings": { - "climbing_club-name": { - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "攀岩 NGO" - } - }, - "render": "攀岩社團" - } - } - }, "title": "開放攀爬地圖" }, "cycle_infra": { @@ -356,71 +337,6 @@ }, "hackerspaces": { "description": "在這份地圖上你可以看到駭客空間,新增或直接更新資料", - "layers": { - "0": { - "description": "駭客空間", - "name": "駭客空間", - "presets": { - "0": { - "description": "駭客空間是對軟體有興趣的人聚集的地方", - "title": "駭客空間" - }, - "1": { - "description": "創客空間是 DIY 愛好者聚集在一起弄電子零件實驗,例如用 arduino、LEDstrips 等...", - "title": "創客空間" - } - }, - "tagRenderings": { - "hackerspaces-name": { - "question": "這個駭客空間的名稱是?", - "render": "這個駭客空間叫 {name}" - }, - "hackerspaces-opening_hours": { - "mappings": { - "0": { - "then": "24/7 營業" - } - }, - "question": "這個駭客空間的營業時間?", - "render": "{opening_hours_table()}" - }, - "hackerspaces-start_date": { - "question": "這個駭客空間何時成立的?", - "render": "這駭客空間是 {start_date} 成立的" - }, - "hs-club-mate": { - "mappings": { - "0": { - "then": "這個駭客空間服務俱樂部伙伴" - }, - "1": { - "then": "這個駭客空間沒有服務俱樂部伙伴" - } - }, - "question": "這個駭客空間是否服務俱樂部伙伴?" - }, - "is_makerspace": { - "mappings": { - "0": { - "then": "這是創客空間" - }, - "1": { - "then": "這是傳統的 (軟體導向) 駭客空間" - } - }, - "question": "這邊是駭客空間還是創客空間?" - } - }, - "title": { - "mappings": { - "0": { - "then": " {name}" - } - }, - "render": "駭客空間" - } - } - }, "shortDescription": "駭客空間的地圖", "title": "駭客空間" }, @@ -441,71 +357,6 @@ }, "openwindpowermap": { "description": "顯示與編輯風機的地圖。", - "layers": { - "0": { - "name": "風機", - "presets": { - "0": { - "title": "風機" - } - }, - "tagRenderings": { - "turbine-diameter": { - "question": "這個風力渦輪機的風葉直徑是多少公尺?", - "render": "這個風力渦輪機的風葉直徑是 {rotor:diameter} 公尺。" - }, - "turbine-height": { - "question": "這個風機的總高度是多少 (包括風葉大小) 公尺?", - "render": "這風機的總高度 (包括風葉直徑) 是 {height} 公尺。" - }, - "turbine-operator": { - "question": "這個風機營業商是?", - "render": "這個風機營業商是 {operator}。" - }, - "turbine-output": { - "question": "這個風機的電力輸出是多少?(例如 2.3 MW)", - "render": "這個風機的電力輸出是 {generator:output:electricity}。" - }, - "turbine-start-date": { - "question": "這個風機何時開始營運?", - "render": "這個風機從 {start_date} 開始運轉。" - } - }, - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "風機" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " 百萬瓦" - }, - "1": { - "human": " 千瓦" - }, - "2": { - "human": " 瓦" - }, - "3": { - "human": " 千兆瓦" - } - } - }, - "1": { - "applicableUnits": { - "0": { - "human": " 公尺" - } - } - } - } - } - }, "title": "開放風力地圖" }, "parkings": { diff --git a/langs/zh_Hans.json b/langs/zh_Hans.json index 9e26dfeeb..380347ac9 100644 --- a/langs/zh_Hans.json +++ b/langs/zh_Hans.json @@ -1 +1,29 @@ -{} \ No newline at end of file +{ + "centerMessage": { + "loadingData": "加载数据中……", + "ready": "完成!", + "retrying": "加载数据失败。将在 {count} 秒后重试……", + "zoomIn": "放大以查看或编辑数据" + }, + "delete": { + "cancel": "取消", + "delete": "删除", + "explanations": { + "hardDelete": "这个点将在OpenStreetMap中被删除。它可以被有经验的贡献者恢复" + }, + "notEnoughExperience": "这个点由其他人创建。", + "onlyEditedByLoggedInUser": "这个点仅被您所编辑,您可以安全的删除它。", + "useSomethingElse": "使用其他OpenStreetMap编辑器来删除它", + "whyDelete": "为什么这个点需要被删除?" + }, + "favourite": { + "reload": "重新加载数据" + }, + "general": { + "aboutMapcomplete": "

    关于MapComplete

    使用它在特定主题上追加OpenStreetMap信息。 Answer questions, and within minutes your contributions are available everywhere. 主题维护者为它定义元素、问题和语言。

    发现更多

    MapComplete always offers the next step to learn more about OpenStreetMap.

    • 当嵌入在网站的时候,iframe连接到一个全屏的MapComplete
    • 全屏版本提供OpenStreetMap信息
    • 无需登录即可查看,但编辑需要一个OSM账号。
    • 若您未登录则将被要求登录
    • 每次当您回答一条问题,您都可以向地图添加新的点
    • After a while, actual OSM-tags are shown, later linking to the wiki


    Did you notice an issue? Do you have a feature request? Want to help translate? Head over to the source code orissue tracker.

    想要查看您的进度?查阅OsmCha上的编辑计数。

    ", + "add": { + "disableFilters": "禁用所有过滤器", + "hasBeenImported": "这个点已经被导入过了" + } + } +} diff --git a/langs/zh_Hant.json b/langs/zh_Hant.json index c7be5a753..e0916e9bf 100644 --- a/langs/zh_Hant.json +++ b/langs/zh_Hant.json @@ -90,130 +90,6 @@ "title": "下載可視的資料" }, "fewChangesBefore": "請先回答有關既有節點的問題再來新增新節點。", - "general": { - "about": "相當容易編輯,而且能為開放街圖新增特定主題", - "aboutMapcomplete": "

    關於 MapComplete

    使用 MapComplete 你可以藉由單一主題豐富開放街圖的圖資。回答幾個問題,然後幾分鐘之內你的貢獻立刻就傳遍全球!主題維護者定議主題的元素、問題與語言。

    發現更多

    MapComplete 總是提供學習更多開放街圖下一步的知識

    • 當你內嵌網站,網頁內嵌會連結到全螢幕的 MapComplete
    • 全螢幕的版本提供關於開放街圖的資訊
    • 不登入檢視成果,但是要編輯則需登入 OSM。
    • 如果你沒有登入,你會被要求先登入
    • 當你回答單一問題時,你可以在地圖新增新的節點
    • 過了一陣子,實際的 OSM-標籤會顯示,之後會連結到 wiki


    你有注意到問題嗎?你想請求功能嗎?想要幫忙翻譯嗎?來到原始碼或是問題追蹤器。

    想要看到你的進度嗎?到OsmCha追蹤編輯數。

    ", - "add": { - "addNew": "在這裡新增新的 {category}", - "confirmButton": "在此新增 {category}。
    大家都可以看到您新增的內容
    ", - "confirmIntro": "

    在這裡新增 {title} ?

    你在這裡新增的節點所有人都看得到。請只有在確定有物件存在的情形下才新增上去,許多應用程式都使用這份資料。", - "intro": "您點擊處目前未有已知的資料。
    ", - "layerNotEnabled": "圖層 {layer} 目前無法使用,請先啟用這圖層再加新的節點", - "openLayerControl": "開啟圖層控制框", - "pleaseLogin": "請先登入來新增節點", - "stillLoading": "目前仍在載入資料,請稍後再來新增節點。", - "title": "新增新的節點?", - "zoomInFurther": "放大來新增新的節點。" - }, - "attribution": { - "attributionContent": "

    所有資料由開放街圖提供,在開放資料庫授權條款之下自由再利用。

    ", - "attributionTitle": "署名通知", - "codeContributionsBy": "MapComplete 是由 {contributors} 和其他 {hiddenCount} 位貢獻者構建而成", - "iconAttribution": { - "title": "使用的圖示" - }, - "mapContributionsBy": "目前檢視的資料由 {contributors} 貢獻編輯", - "mapContributionsByAndHidden": "目前顯到的資料是由 {contributors} 和其他 {hiddenCount} 位貢獻者編輯貢獻", - "themeBy": "由 {author} 維護主題" - }, - "backgroundMap": "背景地圖", - "cancel": "取消", - "customThemeIntro": "

    客製化主題

    觀看這些先前使用者創造的主題。", - "fewChangesBefore": "請先回答有關既有節點的問題再來新增新節點。", - "getStartedLogin": "登入開放街圖帳號來開始", - "getStartedNewAccount": " 或是 註冊新帳號", - "goToInbox": "開啟訊息框", - "layerSelection": { - "title": "選擇圖層", - "zoomInToSeeThisLayer": "放大來看這個圖層" - }, - "loginToStart": "登入之後來回答這問題", - "loginWithOpenStreetMap": "用開放街圖帳號登入", - "morescreen": { - "createYourOwnTheme": "從零開始建立你的 MapComplete 主題", - "intro": "

    看更多主題地圖?

    您喜歡蒐集地理資料嗎?
    還有更多主題。", - "requestATheme": "如果你有客製化要求,請到問題追踪器那邊提出要求", - "streetcomplete": "行動裝置另有類似的應用程式 StreetComplete。" - }, - "nameInlineQuestion": "這個 {category} 的名稱是 $$$", - "noNameCategory": "{category} 沒有名稱", - "noTagsSelected": "沒有選取標籤", - "number": "號碼", - "oneSkippedQuestion": "跳過一個問題", - "openStreetMapIntro": "

    開放的地圖

    如果有一份地圖,任何人都能自由使用與編輯,單一的地圖能夠儲存所有地理相關資訊?這樣不就很酷嗎?接著,所有的網站使用不同的、範圍小的,不相容的地圖 (通常也都過時了),也就不再需要了。

    開放街圖就是這樣的地圖,人人都能免費這些圖資 (只要署名與公開變動這資料)。只要遵循這些,任何人都能自由新增新資料與修正錯誤,這些網站也都使用開放街圖,資料也都來自開放街圖,你的答案與修正也會加到開放街圖上面。

    許多人與應用程式已經採用開放街圖了:Organic MapsOsmAnd,還有 Facebook、Instagram,蘋果地圖、Bing 地圖(部分)採用開放街圖。如果你在開放街圖上變動資料,也會同時影響這些應用 - 在他們下次更新資料之後!

    ", - "opening_hours": { - "closed_permanently": "不清楚關閉多久了", - "closed_until": "{date} 起關閉", - "error_loading": "錯誤:無法視覺化開放時間。", - "not_all_rules_parsed": "這間店的開放時間相當複雜,在輸入元素時忽略接下來的規則:", - "openTill": "結束時間", - "open_24_7": "24小時營業", - "open_during_ph": "國定假日的時候,這個場所是", - "opensAt": "開始時間", - "ph_closed": "無營業", - "ph_not_known": " ", - "ph_open": "有營業" - }, - "osmLinkTooltip": "在開放街圖歷史和更多編輯選項下面來檢視這物件", - "pickLanguage": "選擇語言: ", - "questions": { - "emailIs": "{category} 的電子郵件地址是{email}", - "emailOf": "{category} 的電子郵件地址是?", - "phoneNumberIs": "此 {category} 的電話號碼為 {phone}", - "phoneNumberOf": "{category} 的電話號碼是?", - "websiteIs": "網站:{website}", - "websiteOf": "{category} 的網站網址是?" - }, - "readYourMessages": "請先閱讀開放街圖訊息之前再來新增新節點。", - "returnToTheMap": "回到地圖", - "save": "儲存", - "search": { - "error": "有狀況發生了…", - "nothing": "沒有找到…", - "search": "搜尋地點", - "searching": "搜尋中…" - }, - "sharescreen": { - "addToHomeScreen": "

    新增到您的主畫面

    您可以輕易將這網站新增到您智慧型手機的主畫面,在網址列點選「新增到主畫面按鈕」來做這件事情。", - "copiedToClipboard": "複製連結到簡貼簿", - "editThemeDescription": "新增或改變這個地圖的問題", - "editThisTheme": "編輯這個主題", - "embedIntro": "

    嵌入到你的網站

    請考慮將這份地圖嵌入您的網站。
    地圖毋須額外授權,非常歡迎您多加利用。
    一切都是免費的,而且之後也是免費的,越有更多人使用,則越顯得它的價值。", - "fsAddNew": "啟用'新增新的興趣點'按鈕", - "fsGeolocation": "啟用'地理定位自身'按鈕 (只有行動版本)", - "fsIncludeCurrentBackgroundMap": "包含目前背景選擇{name}", - "fsIncludeCurrentLayers": "包含目前選擇圖層", - "fsIncludeCurrentLocation": "包含目前位置", - "fsLayerControlToggle": "開始時擴展圖層控制", - "fsLayers": "啟用圖層控制", - "fsSearch": "啟用搜尋列", - "fsUserbadge": "啟用登入按鈕", - "fsWelcomeMessage": "顯示歡迎訊息以及相關頁籤", - "intro": "

    分享這地圖

    複製下面的連結來向朋友與家人分享這份地圖:", - "thanksForSharing": "感謝分享!" - }, - "skip": "跳過這問題", - "skippedQuestions": "有些問題已經跳過了", - "weekdays": { - "abbreviations": { - "friday": "星期五", - "monday": "星期一", - "saturday": "星期六", - "sunday": "星期日", - "thursday": "星期四", - "tuesday": "星期二", - "wednesday": "星期三" - }, - "friday": "星期五", - "monday": "星期一", - "saturday": "星期六", - "sunday": "星期日", - "thursday": "星期四", - "tuesday": "星期二", - "wednesday": "星期三" - }, - "welcomeBack": "你已經登入了,歡迎回來!" - }, "getStartedLogin": "登入開放街圖帳號來開始", "getStartedNewAccount": " 或是 註冊新帳號", "goToInbox": "開啟訊息框", diff --git a/package.json b/package.json index cd3536ab8..1488ede86 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "clean:tests": "(find . -type f -name \"*.doctest.ts\" | xargs rm)", "clean": "rm -rf .cache/ && (find *.html | grep -v \"\\(404\\|index\\|land\\|test\\|preferences\\|customGenerator\\|professional\\|automaton\\|import_helper\\|import_viewer\\|theme\\).html\" | xargs rm) && (ls | grep \"^index_[a-zA-Z_-]\\+\\.ts$\" | xargs rm) && (ls | grep \".*.webmanifest$\" | xargs rm)", "generate:dependency-graph": "node_modules/.bin/depcruise --exclude \"^node_modules\" --output-type dot Logic/State/MapState.ts > dependencies.dot && dot dependencies.dot -T svg -o dependencies.svg && rm dependencies.dot", - "script": "ts-node" + "script": "ts-node", + "merge-translations": "git remote update weblate ; git merge weblate/master" }, "keywords": [ "OpenStreetMap", diff --git a/scripts/automoveTranslations.ts b/scripts/automoveTranslations.ts new file mode 100644 index 000000000..662b91fb0 --- /dev/null +++ b/scripts/automoveTranslations.ts @@ -0,0 +1,61 @@ +import * as languages from "../assets/generated/used_languages.json" +import {readFileSync, writeFileSync} from "fs"; + +/** + * Moves values around in 'section'. Section will be changed + * @param section + * @param referenceSection + * @param language + */ +function fixSection(section, referenceSection, language: string) { + if(section === undefined){ + return + } + outer: for (const key of Object.keys(section)) { + const v = section[key] + if(typeof v ==="string" && referenceSection[key] === undefined){ + // Not found in reference, search for a subsection with this key + for (const subkey of Object.keys(referenceSection)) { + const subreference = referenceSection[subkey] + if(subreference[key] !== undefined){ + if(section[subkey] !== undefined && section[subkey][key] !== undefined) { + console.log(`${subkey}${key} is already defined... Looking furhter`) + continue + } + if(typeof section[subkey] === "string"){ + console.log(`NOT overwriting '${section[subkey]}' for ${subkey} (needed for ${key})`) + }else{ + // apply fix + if(section[subkey] === undefined){ + section[subkey] = {} + } + section[subkey][key] = section[key] + delete section[key] + console.log(`Rewritten key: ${key} --> ${subkey}.${key} in language ${language}`) + continue outer + } + } + } + console.log("No solution found for "+key) + } + } +} + + +function main(args:string[]):void{ + const sectionName = args[0] + const l = args[1] + if(sectionName === undefined){ + console.log("Tries to automatically move translations to a new subsegment. Usage: 'sectionToCheck' 'language'") + return + } + const reference = JSON.parse( readFileSync("./langs/en.json","UTF8")) + const path = `./langs/${l}.json` + const file = JSON.parse( readFileSync(path,"UTF8")) + fixSection(file[sectionName], reference[sectionName], l) + writeFileSync(path, JSON.stringify(file, null, " ")+"\n") + + +} + +main(process.argv.slice(2)) \ No newline at end of file diff --git a/scripts/extractLayer.ts b/scripts/extractLayer.ts new file mode 100644 index 000000000..827642a69 --- /dev/null +++ b/scripts/extractLayer.ts @@ -0,0 +1,54 @@ +import {LayoutConfigJson} from "../Models/ThemeConfig/Json/LayoutConfigJson"; +import {LayerConfigJson} from "../Models/ThemeConfig/Json/LayerConfigJson"; +import {existsSync, mkdirSync, readFileSync, writeFileSync} from "fs"; + +function main(args: string[]){ + if(args.length === 0){ + console.log("Extracts an inline layer from a theme and places it in it's own layer directory.") + console.log("USAGE: ts-node scripts/extractLayerFromTheme.ts ") + console.log("(Invoke with only the themename to see which layers can be extracted)") + return + } + const themeId = args[0] + const layerId = args[1] + + const themePath = "./assets/themes/"+themeId+"/"+themeId+".json" + const contents = JSON.parse(readFileSync(themePath, "UTF-8")) + const layers = contents.layers.filter(l => { + if(typeof l === "string"){ + return false + } + if(l["override"] !== undefined){ + return false + } + return true + }) + + if(layers.length === 0){ + console.log("No layers can be extracted from this theme. The "+contents.layers.length+" layers are already substituted layers") + return + } + + const layerConfig = layers.find(l => l.id === layerId) + if(layerId === undefined || layerConfig === undefined){ + if(layerId !== undefined){ + console.error( "Layer "+layerId+" not found as inline layer") + } + console.log("Layers available for extraction are:") + console.log(layers.map(l => l.id).join("\n")) + return + } + + + const dir = "./assets/layers/"+layerId + if(!existsSync(dir)){ + mkdirSync(dir) + } + writeFileSync(dir+"/"+layerId+".json", JSON.stringify(layerConfig, null, " ")) + + const index = contents.layers.findIndex(l => l["id"] === layerId) + contents.layers[index] = layerId + writeFileSync(themePath, JSON.stringify(contents, null, " ")) +} + +main(process.argv.slice(2)) \ No newline at end of file diff --git a/scripts/fetchLanguages.ts b/scripts/fetchLanguages.ts index 2abf82e8f..69aa952ea 100644 --- a/scripts/fetchLanguages.ts +++ b/scripts/fetchLanguages.ts @@ -93,12 +93,15 @@ function extract(data){ function getNativeList(langs: Map>){ const native = {} - langs.forEach((translations, key ) =>{ + const keys: string[] = Array.from(langs.keys()) + keys.sort() + for (const key of keys) { + const translations: Map = langs.get(key) if(!usedLanguages.has(key)){ - return + continue } native[key] = translations.get(key) - }) + } return native } diff --git a/scripts/filter.ts b/scripts/filter.ts new file mode 100644 index 000000000..1a9713658 --- /dev/null +++ b/scripts/filter.ts @@ -0,0 +1,45 @@ +import * as fs from "fs"; +import {TagUtils} from "../Logic/Tags/TagUtils"; +import {writeFileSync} from "fs"; +import {TagsFilter} from "../Logic/Tags/TagsFilter"; + +function main(args) { + if (args.length < 2) { + console.log("Given a single geojson file and a filter specification, will print all the entries to std-out which pass the property") + console.log("USAGE: perProperty `file.geojson` `key=value` [outputfile]") + return + } + const path = args[0] + const spec = args[1] + const output = args[2] + + const data = JSON.parse(fs.readFileSync(path, "UTF8")) + let filter : TagsFilter ; + try{ + filter = TagUtils.Tag(JSON.parse(spec)) + + }catch(e){ + filter = TagUtils.Tag(spec) + } + const features = data.features.filter(f => filter.matchesProperties(f.properties)) + + if(features.length === 0){ + console.log("Warning: no features matched the filter. Exiting now") + return + } + + const collection = { + type:"FeatureCollection", + features + } + const stringified = JSON.stringify(collection, null, " ") + if(output === undefined){ + console.log(stringified) + }else{ + console.log("Filtered "+path+": kept "+features.length+" out of "+data.features.length+" objects") + writeFileSync(output, stringified) + } + +} + +main(process.argv.slice(2)) \ No newline at end of file diff --git a/scripts/generateContributors.ts b/scripts/generateContributors.ts index 408f07dd4..66e06a9e2 100644 --- a/scripts/generateContributors.ts +++ b/scripts/generateContributors.ts @@ -27,7 +27,7 @@ function main() { author = "Pieter Vander Vennet" } let hist = codeContributors; - if (message.startsWith("Translated using Weblate")) { + if (message.startsWith("Translated using Weblate") || message.startsWith("Translated using Hosted Weblate")) { hist = translationContributors } hist.set(author, 1 + (hist.get(author) ?? 0)) diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index d9faf2d9a..02cc13859 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -203,16 +203,22 @@ class LayerOverviewUtils { const themePath = themeInfo.path new PrevalidateTheme().convertStrict(themeFile, themePath) - themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath) - - if(knownImagePaths === undefined){ - throw "Could not load known images/licenses" + try{ + + themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath) + + if(knownImagePaths === undefined){ + throw "Could not load known images/licenses" + } + new ValidateThemeAndLayers(knownImagePaths, themePath, true, convertState.tagRenderings) + .convertStrict(themeFile, themePath) + + this.writeTheme(themeFile) + fixed.set(themeFile.id, themeFile) + }catch(e){ + console.error("ERROR: could not prepare theme "+themePath+" due to "+e) + throw e; } - new ValidateThemeAndLayers(knownImagePaths, themePath, true, convertState.tagRenderings) - .convertStrict(themeFile, themePath) - - this.writeTheme(themeFile) - fixed.set(themeFile.id, themeFile) } this.writeSmallOverview(themeFiles.map(tf => { diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index 7711d7678..546d26350 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -161,8 +161,8 @@ async function createManifest(layout: LayoutConfig, alreadyWritten: string[]): P console.log(icon) throw "Icon is not an svg for " + layout.id } - const ogTitle = Translations.WT(layout.title).txt; - const ogDescr = Translations.WT(layout.description ?? "").txt; + const ogTitle = Translations.T(layout.title).txt; + const ogDescr = Translations.T(layout.description ?? "").txt; const manifest = { name: name, @@ -186,8 +186,8 @@ async function createLandingPage(layout: LayoutConfig, manifest, whiteIcons, alr Locale.language.setData(layout.language[0]); const targetLanguage = layout.language[0] - const ogTitle = Translations.WT(layout.title).textFor(targetLanguage).replace(/"/g, '\\"'); - const ogDescr = Translations.WT(layout.shortDescription ?? "Easily add and edit geodata with OpenStreetMap").textFor(targetLanguage).replace(/"/g, '\\"'); + const ogTitle = Translations.T(layout.title).textFor(targetLanguage).replace(/"/g, '\\"'); + const ogDescr = Translations.T(layout.shortDescription ?? "Easily add and edit geodata with OpenStreetMap").textFor(targetLanguage).replace(/"/g, '\\"'); let ogImage = layout.socialImage; let twitterImage = ogImage if (ogImage === LayoutConfig.defaultSocialImage && layout.official) { @@ -303,7 +303,7 @@ async function main(): Promise { if (theme !== undefined && layoutConfigJson.id !== theme) { continue } - const layout = new LayoutConfig(layoutConfigJson, true, "generating layouts") + const layout = new LayoutConfig(layoutConfigJson, true) const layoutName = layout.id if (blacklist.indexOf(layoutName.toLowerCase()) >= 0) { console.log(`Skipping a layout with name${layoutName}, it is on the blacklist`); diff --git a/scripts/generateTranslations.ts b/scripts/generateTranslations.ts index d94873d99..0f83f30ba 100644 --- a/scripts/generateTranslations.ts +++ b/scripts/generateTranslations.ts @@ -297,7 +297,20 @@ function transformTranslation(obj: any, path: string[] = [], languageWhitelist : } value = nv; } - values += `${Utils.Times((_) => " ", path.length + 1)}get ${key}() { return new Translation(${JSON.stringify(value)}, "core:${path.join(".")}.${key}") }, + + + if(value["en"] === undefined){ + throw `At ${path.join(".")}: Missing 'en' translation at path ${path.join(".")}.${key}\n\tThe translations in other languages are ${JSON.stringify(value)}` + } + const subParts : string[] = value["en"].match(/{[^}]*}/g) + let expr = `return new Translation(${JSON.stringify(value)}, "core:${path.join(".")}.${key}")` + if(subParts !== null){ + // convert '{to_substitute}' into 'to_substitute' + const types = Utils.Dedup( subParts.map(tp => tp.substring(1, tp.length - 1))) + expr = `return new TypedTranslation<{ ${types.join(", ")} }>(${JSON.stringify(value)}, "core:${path.join(".")}.${key}")` + } + + values += `${Utils.Times((_) => " ", path.length + 1)}get ${key}() { ${expr} }, ` } else { values += (Utils.Times((_) => " ", path.length + 1)) + key + ": " + transformTranslation(value, [...path, key], languageWhitelist) + ",\n" @@ -340,7 +353,7 @@ function genTranslations() { const translations = JSON.parse(fs.readFileSync("./assets/generated/translations.json", "utf-8")) const transformed = transformTranslation(translations); - let module = `import {Translation} from "../../UI/i18n/Translation"\n\nexport default class CompiledTranslations {\n\n`; + let module = `import {Translation, TypedTranslation} from "../../UI/i18n/Translation"\n\nexport default class CompiledTranslations {\n\n`; module += " public static t = " + transformed; module += "\n }" @@ -569,14 +582,12 @@ if (!themeOverwritesWeblate) { genTranslations() const allTranslationFiles = ScriptUtils.readDirRecSync("langs").filter(path => path.endsWith(".json")) for (const path of allTranslationFiles) { - console.log("Formatting ", path) formatFile(path) } - // Some validation TranslationPart.fromDirectory("./langs").validateStrict("./langs") TranslationPart.fromDirectory("./langs/layers").validateStrict("layers") TranslationPart.fromDirectory("./langs/themes").validateStrict("themes") TranslationPart.fromDirectory("./langs/shared-questions").validateStrict("shared-questions") - +console.log("All done!") diff --git a/scripts/generateWikiPage.ts b/scripts/generateWikiPage.ts index 1c06c0f53..0e7a7ac28 100644 --- a/scripts/generateWikiPage.ts +++ b/scripts/generateWikiPage.ts @@ -18,7 +18,7 @@ function generateWikiEntry(layout: { hideFromOverview: boolean, id: string, shor |name= [https://mapcomplete.osm.be/${layout.id} ${layout.id}] |region= Worldwide |lang= ${languages} -|descr= A MapComplete theme: ${Translations.WT(layout.shortDescription) +|descr= A MapComplete theme: ${Translations.T(layout.shortDescription) .textFor("en") .replace(".*<\/a>/, "]]") diff --git a/scripts/lint.ts b/scripts/lint.ts index 3ac0cc076..220bb3cc2 100644 --- a/scripts/lint.ts +++ b/scripts/lint.ts @@ -57,22 +57,6 @@ function addArticleToPresets(layerConfig: {presets?: {title: any}[]}){ //*/ } -function extractInlineLayer(theme: LayoutConfigJson){ - for (let i = 0; i < theme.layers.length; i++){ - const layer = theme.layers[i]; - if(typeof layer === "string"){ - continue - } - if(layer["override"] !== undefined){ - continue - } - const l = layer - mkdirSync("./assets/layers/"+l.id) - writeFileSync("./assets/layers/"+l.id+"/"+l.id+".json", JSON.stringify(l, null, " ")) - theme.layers[i] = l.id - } -} - const layerFiles = ScriptUtils.getLayerFiles(); for (const layerFile of layerFiles) { try { diff --git a/scripts/perProperty.ts b/scripts/perProperty.ts index 9349499d1..30e796fba 100644 --- a/scripts/perProperty.ts +++ b/scripts/perProperty.ts @@ -2,7 +2,7 @@ import * as fs from "fs"; function main(args) { if (args.length < 2) { - console.log("Given a single geojson file, generates the partitions for every found property") + console.log("Given a single geojson file and an attribute-key, will generate a new file for every value of the partition.") console.log("USAGE: perProperty `file.geojson` `property-key`") return } @@ -35,11 +35,4 @@ function main(args) { } -let args = [...process.argv] -args.splice(0, 2) -try { - main(args) -} catch (e) { - console.error("Error building cache:", e) -} -console.log("All done!") \ No newline at end of file +main(process.argv.slice(2)) diff --git a/test.ts b/test.ts index 9a6b02f97..4640df0ca 100644 --- a/test.ts +++ b/test.ts @@ -1,31 +1,17 @@ -import Combine from "./UI/Base/Combine"; -import ValidatedTextField from "./UI/Input/ValidatedTextField"; -import Title from "./UI/Base/Title"; -import {FixedUiElement} from "./UI/Base/FixedUiElement"; import {VariableUiElement} from "./UI/Base/VariableUIElement"; import {UIEventSource} from "./Logic/UIEventSource"; -import {Translation} from "./UI/i18n/Translation"; +import Wikidata from "./Logic/Web/Wikidata"; +import Combine from "./UI/Base/Combine"; +import {FixedUiElement} from "./UI/Base/FixedUiElement"; -new Combine( - ValidatedTextField.AvailableTypes().map(key => { - let inp; - const feedback = new UIEventSource(undefined) - try { - inp = ValidatedTextField.ForType(key).ConstructInputElement({ - feedback, - country: () => "be" - }); - } catch (e) { - console.error(e) - inp = new FixedUiElement(e).SetClass("alert") - } - - return new Combine([ - new Title(key), - inp, - new VariableUiElement(inp.GetValue()), - new VariableUiElement(feedback.map(v => v?.SetClass("alert"))) - ]); - } - ) -).AttachTo("maindiv") \ No newline at end of file +const result = UIEventSource.FromPromise( + Wikidata.searchAdvanced("WOlf", { + lang: "nl", + maxCount: 100, + instanceOf: 5 + }) +) +result.addCallbackAndRunD(r => console.log(r)) +new VariableUiElement(result.map(items =>new Combine( (items??[])?.map(i => + new FixedUiElement(JSON.stringify(i, null, " ")).SetClass("p-4 block") +)) )).SetClass("flex flex-col").AttachTo("maindiv") \ No newline at end of file diff --git a/test/Logic/Actors/Actors.spec.ts b/test/Logic/Actors/Actors.spec.ts index 334647c56..2aed28b52 100644 --- a/test/Logic/Actors/Actors.spec.ts +++ b/test/Logic/Actors/Actors.spec.ts @@ -47,7 +47,7 @@ Utils.injectJsonDownloadForTests( ) it("should download the latest version", () => { - const state = new UserRelatedState(new LayoutConfig( bookcaseJson, true, "tests")) + const state = new UserRelatedState(new LayoutConfig( bookcaseJson, true)) const feature = { "type": "Feature", "id": "node/5568693115", diff --git a/test/Logic/Tags/OptimizeTags.spec.ts b/test/Logic/Tags/OptimizeTags.spec.ts new file mode 100644 index 000000000..5229c94a0 --- /dev/null +++ b/test/Logic/Tags/OptimizeTags.spec.ts @@ -0,0 +1,347 @@ +import {describe} from 'mocha' +import {expect} from 'chai' +import {TagsFilter} from "../../../Logic/Tags/TagsFilter"; +import {And} from "../../../Logic/Tags/And"; +import {Tag} from "../../../Logic/Tags/Tag"; +import {TagUtils} from "../../../Logic/Tags/TagUtils"; +import {Or} from "../../../Logic/Tags/Or"; +import {RegexTag} from "../../../Logic/Tags/RegexTag"; + +describe("Tag optimalization", () => { + + describe("And", () => { + it("with condition and nested and should be flattened", () => { + const t = new And( + [ + new And([ + new Tag("x", "y") + ]), + new Tag("a", "b") + ] + ) + const opt = t.optimize() + expect(TagUtils.toString(opt)).eq(`a=b&x=y`) + }) + + it("should be 'true' if no conditions are given", () => { + const t = new And( + [] + ) + const opt = t.optimize() + expect(opt).eq(true) + }) + + it("with nested ors and common property should be extracted", () => { + + // foo&bar & (x=y | a=b) & (x=y | c=d) & foo=bar is equivalent too foo=bar & ((x=y) | (a=b & c=d)) + const t = new And([ + new Tag("foo", "bar"), + new Or([ + new Tag("x", "y"), + new Tag("a", "b") + ]), + new Or([ + new Tag("x", "y"), + new Tag("c", "d") + ]) + ]) + const opt = t.optimize() + expect(TagUtils.toString(opt)).eq("foo=bar& (x=y| (a=b&c=d) )") + }) + + it("with nested ors and common regextag should be extracted", () => { + + // foo&bar & (x=y | a=b) & (x=y | c=d) & foo=bar is equivalent too foo=bar & ((x=y) | (a=b & c=d)) + const t = new And([ + new Tag("foo", "bar"), + new Or([ + new RegexTag("x", "y"), + new RegexTag("a", "b") + ]), + new Or([ + new RegexTag("x", "y"), + new RegexTag("c", "d") + ]) + ]) + const opt = t.optimize() + expect(TagUtils.toString(opt)).eq("foo=bar& ( (a=b&c=d) |x=y)") + }) + + it("with nested ors and inverted regextags should _not_ be extracted", () => { + + // foo&bar & (x=y | a=b) & (x=y | c=d) & foo=bar is equivalent too foo=bar & ((x=y) | (a=b & c=d)) + const t = new And([ + new Tag("foo", "bar"), + new Or([ + new RegexTag("x", "y"), + new RegexTag("a", "b") + ]), + new Or([ + new RegexTag("x", "y", true), + new RegexTag("c", "d") + ]) + ]) + const opt = t.optimize() + expect(TagUtils.toString(opt)).eq("foo=bar& (a=b|x=y) & (c=d|x!=y)") + }) + + it("should move regextag to the end", () => { + const t = new And([ + new RegexTag("x", "y"), + new Tag("a", "b") + ]) + const opt = t.optimize() + expect(TagUtils.toString(opt)).eq("a=b&x=y") + + }) + + it("should sort tags by their popularity (least popular first)", () => { + const t = new And([ + new Tag("bicycle", "yes"), + new Tag("amenity", "binoculars") + ]) + const opt = t.optimize() + expect(TagUtils.toString(opt)).eq("amenity=binoculars&bicycle=yes") + + }) + + it("should optimize nested ORs", () => { + const filter = TagUtils.Tag({ + or: [ + "X=Y", "FOO=BAR", + { + "and": [ + { + "or": ["X=Y", "FOO=BAR"] + }, + "bicycle=yes" + ] + } + ] + }) + // (X=Y | FOO=BAR | (bicycle=yes & (X=Y | FOO=BAR)) ) + // This is equivalent to (X=Y | FOO=BAR) + const opt = filter.optimize() + console.log(opt) + }) + + it("should optimize an advanced, real world case", () => { + const filter = TagUtils.Tag({ + or: [ + { + "and": [ + { + "or": ["amenity=charging_station", "disused:amenity=charging_station", "planned:amenity=charging_station", "construction:amenity=charging_station"] + }, + "bicycle=yes" + ] + }, + { + "and": [ + { + "or": ["amenity=charging_station", "disused:amenity=charging_station", "planned:amenity=charging_station", "construction:amenity=charging_station"] + }, + ] + }, + "amenity=toilets", + "amenity=bench", + "leisure=picnic_table", + { + "and": [ + "tower:type=observation" + ] + }, + { + "and": [ + "amenity=bicycle_repair_station" + ] + }, + { + "and": [ + { + "or": [ + "amenity=bicycle_rental", + "bicycle_rental~*", + "service:bicycle:rental=yes", + "rental~.*bicycle.*" + ] + }, + "bicycle_rental!=docking_station" + ] + }, + { + "and": [ + "leisure=playground", + "playground!=forest" + ] + } + ] + }); + const opt = filter.optimize() + const expected = ["amenity=charging_station", + "amenity=toilets", + "amenity=bench", + "amenity=bicycle_repair_station", + "construction:amenity=charging_station", + "disused:amenity=charging_station", + "leisure=picnic_table", + "planned:amenity=charging_station", + "tower:type=observation", + "(amenity=bicycle_rental|service:bicycle:rental=yes|bicycle_rental~^..*$|rental~^.*bicycle.*$) &bicycle_rental!=docking_station", + "leisure=playground&playground!=forest"] + + expect((opt).or.map(f => TagUtils.toString(f))).deep.eq( + expected + ) + }) + + it("should detect conflicting tags", () => { + const q = new And([new Tag("key", "value"), new RegexTag("key", "value", true)]) + expect(q.optimize()).eq(false) + }) + + it("should detect conflicting tags with a regex", () => { + const q = new And([new Tag("key", "value"), new RegexTag("key", /value/, true)]) + expect(q.optimize()).eq(false) + }) + + }) + + describe("Or", () => { + + + it("with nested And which has a common property should be dropped", () => { + + const t = new Or([ + new Tag("foo", "bar"), + new And([ + new Tag("foo", "bar"), + new Tag("x", "y"), + ]) + ]) + const opt = t.optimize() + expect(TagUtils.toString(opt)).eq("foo=bar") + + }) + + it("should flatten nested ors", () => { + const t = new Or([ + new Or([ + new Tag("x", "y") + ]) + ]).optimize() + expect(t).deep.eq(new Tag("x", "y")) + }) + + it("should flatten nested ors", () => { + const t = new Or([ + new Tag("a", "b"), + new Or([ + new Tag("x", "y") + ]) + ]).optimize() + expect(t).deep.eq(new Or([new Tag("a", "b"), new Tag("x", "y")])) + }) + + }) + + it("should not generate a conflict for climbing tags", () => { + const club_tags = TagUtils.Tag( + { + "or": [ + "club=climbing", + { + "and": [ + "sport=climbing", + { + "or": [ + "office~*", + "club~*" + ] + } + ] + } + ] + }) + const gym_tags = TagUtils.Tag({ + "and": [ + "sport=climbing", + "leisure=sports_centre" + ] + }) + const other_climbing = TagUtils.Tag({ + "and": [ + "sport=climbing", + "climbing!~route", + "leisure!~sports_centre", + "climbing!=route_top", + "climbing!=route_bottom" + ] + }) + const together = new Or([club_tags, gym_tags, other_climbing]) + const opt = together.optimize() + + /* + club=climbing | (sport=climbing&(office~* | club~*)) + OR + sport=climbing & leisure=sports_centre + OR + sport=climbing & climbing!~route & leisure!~sports_centre + */ + + /* + > When the first OR is written out, this becomes + club=climbing + OR + (sport=climbing&(office~* | club~*)) + OR + (sport=climbing & leisure=sports_centre) + OR + (sport=climbing & climbing!~route & leisure!~sports_centre & ...) + */ + + /* + > We can join the 'sport=climbing' in the last 3 phrases + club=climbing + OR + (sport=climbing AND + (office~* | club~*)) + OR + (leisure=sports_centre) + OR + (climbing!~route & leisure!~sports_centre & ...) + ) + */ + + + expect(opt).deep.eq( + TagUtils.Tag({ + or: [ + "club=climbing", + { + and: ["sport=climbing", + {or: ["club~*", "office~*"]}] + }, + { + and: ["sport=climbing", + { + or: [ + "leisure=sports_centre", + { + and: [ + "climbing!~route", + "climbing!=route_top", + "climbing!=route_bottom", + "leisure!~sports_centre" + ] + } + ] + }] + } + + ], + + }) + ) + }) +}) \ No newline at end of file diff --git a/test/Logic/Tags/OptimzeTags.spec.ts b/test/Logic/Tags/OptimzeTags.spec.ts deleted file mode 100644 index 46870ff53..000000000 --- a/test/Logic/Tags/OptimzeTags.spec.ts +++ /dev/null @@ -1,150 +0,0 @@ -import {describe} from 'mocha' -import {expect} from 'chai' -import {TagsFilter} from "../../../Logic/Tags/TagsFilter"; -import {And} from "../../../Logic/Tags/And"; -import {Tag} from "../../../Logic/Tags/Tag"; -import {TagUtils} from "../../../Logic/Tags/TagUtils"; -import {Or} from "../../../Logic/Tags/Or"; -import {RegexTag} from "../../../Logic/Tags/RegexTag"; - -describe("Tag optimalization", () => { - - describe("And", () => { - it("with condition and nested and should be flattened", () => { - const t = new And( - [ - new And([ - new Tag("x", "y") - ]), - new Tag("a", "b") - ] - ) - const opt = t.optimize() - expect(TagUtils.toString(opt)).eq(`a=b&x=y`) - }) - - it("with nested ors and commons property should be extracted", () => { - - // foo&bar & (x=y | a=b) & (x=y | c=d) & foo=bar is equivalent too foo=bar & ((x=y) | (a=b & c=d)) - const t = new And([ - new Tag("foo","bar"), - new Or([ - new Tag("x", "y"), - new Tag("a", "b") - ]), - new Or([ - new Tag("x", "y"), - new Tag("c", "d") - ]) - ]) - const opt = t.optimize() - expect(TagUtils.toString(opt)).eq("foo=bar& (x=y| (a=b&c=d) )") - }) - - it("should move regextag to the end", () => { - const t = new And([ - new RegexTag("x","y"), - new Tag("a","b") - ]) - const opt = t.optimize() - expect(TagUtils.toString(opt)).eq("a=b&x~^y$") - - }) - - it("should sort tags by their popularity (least popular first)", () => { - const t = new And([ - new Tag("bicycle","yes"), - new Tag("amenity","binoculars") - ]) - const opt = t.optimize() - expect(TagUtils.toString(opt)).eq("amenity=binoculars&bicycle=yes") - - }) - - it("should optimize an advanced, real world case", () => { - const filter = TagUtils.Tag( {or: [ - { - "and": [ - { - "or": ["amenity=charging_station","disused:amenity=charging_station","planned:amenity=charging_station","construction:amenity=charging_station"] - }, - "bicycle=yes" - ] - }, - { - "and": [ - { - "or": ["amenity=charging_station","disused:amenity=charging_station","planned:amenity=charging_station","construction:amenity=charging_station"] - }, - ] - }, - "amenity=toilets", - "amenity=bench", - "leisure=picnic_table", - { - "and": [ - "tower:type=observation" - ] - }, - { - "and": [ - "amenity=bicycle_repair_station" - ] - }, - { - "and": [ - { - "or": [ - "amenity=bicycle_rental", - "bicycle_rental~*", - "service:bicycle:rental=yes", - "rental~.*bicycle.*" - ] - }, - "bicycle_rental!=docking_station" - ] - }, - { - "and": [ - "leisure=playground", - "playground!=forest" - ] - } - ]}); - const opt = filter.optimize() - const expected = "amenity=charging_station|" + - "amenity=toilets|" + - "amenity=bench|" + - "amenity=bicycle_repair_station" + - "|construction:amenity=charging_station|" + - "disused:amenity=charging_station|" + - "leisure=picnic_table|" + - "planned:amenity=charging_station|" + - "tower:type=observation| " + - "( (amenity=bicycle_rental|service:bicycle:rental=yes|bicycle_rental~^..*$|rental~^.*bicycle.*$) &bicycle_rental!~^docking_station$) |" + - " (leisure=playground&playground!~^forest$)" - - expect(TagUtils.toString(opt).replace(/ /g, "")) - .eq(expected.replace(/ /g, "")) - - }) - - }) - - describe("Or", () => { - it("with nested And which has a common property should be dropped", () => { - - const t = new Or([ - new Tag("foo","bar"), - new And([ - new Tag("foo", "bar"), - new Tag("x", "y"), - ]) - ]) - const opt = t.optimize() - expect(TagUtils.toString(opt)).eq("foo=bar") - - }) - - }) -}) \ No newline at end of file diff --git a/test/Models/ThemeConfig/Conversion/FixLegacyTheme.spec.ts b/test/Models/ThemeConfig/Conversion/FixLegacyTheme.spec.ts index e61496bd2..0fbe04cca 100644 --- a/test/Models/ThemeConfig/Conversion/FixLegacyTheme.spec.ts +++ b/test/Models/ThemeConfig/Conversion/FixLegacyTheme.spec.ts @@ -145,7 +145,7 @@ describe("FixLegacyTheme", () => { walking_node_theme, "While testing") expect(fixed.errors, "Could not fix the legacy theme").empty - const theme = new LayoutConfig(fixed.result, false,"test") + const theme = new LayoutConfig(fixed.result, false) expect(theme).not.undefined }) diff --git a/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts b/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts index b18863ce7..2a06069ca 100644 --- a/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts +++ b/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts @@ -10,6 +10,7 @@ import LayerConfig from "../../../../Models/ThemeConfig/LayerConfig"; import {ExtractImages} from "../../../../Models/ThemeConfig/Conversion/FixImages"; import * as cyclofix from "../../../../assets/generated/themes/cyclofix.json" import {Tag} from "../../../../Logic/Tags/Tag"; +import {DesugaringContext} from "../../../../Models/ThemeConfig/Conversion/Conversion"; const themeConfigJson: LayoutConfigJson = { @@ -69,7 +70,6 @@ describe("PrepareTheme", () => { }) - it("should apply override", () => { const sharedLayers = new Map() @@ -82,8 +82,65 @@ describe("PrepareTheme", () => { const layerUnderTest = themeConfig.layers.find(l => l.id === "public_bookcase") expect(layerUnderTest.source.geojsonSource).eq("https://example.com/data.geojson") }) -}) + + it("should remove names which are overriden with null", () => { + const testLayer: LayerConfigJson = { + source: { + osmTags: "x=y" + }, + id: "layer-example", + name: { + en: "Test layer - please ignore" + }, + titleIcons : [], + mapRendering: null + } + const ctx: DesugaringContext = { + sharedLayers: new Map([[ + "layer-example", testLayer + ]]), + tagRenderings: new Map() + } + const layout : LayoutConfigJson= + { + description: "A testing theme", + icon: "", + id: "", + layers: [ + "layer-example", + { + "builtin": "layer-example", + "override": { + "name": null, + "minzoom": 18 + } + } + ], + maintainer: "Me", + startLat: 0, + startLon: 0, + startZoom: 0, + title: "Test theme", + version: "" + + } + const rewritten = new PrepareTheme(ctx, { + skipDefaultLayers: true + }).convertStrict(layout, "test") + expect(rewritten.layers[0]).deep.eq(testLayer) + expect(rewritten.layers[1]).deep.eq({ + source: { + osmTags: "x=y" + }, + id: "layer-example", + name:null, + minzoom: 18, + mapRendering: null, + titleIcons: [] + }) + }) +}) describe("ExtractImages", () => { it("should find all images in a themefile", () => { diff --git a/test/Models/ThemeConfig/SourceConfig.spec.ts b/test/Models/ThemeConfig/SourceConfig.spec.ts new file mode 100644 index 000000000..97c590e87 --- /dev/null +++ b/test/Models/ThemeConfig/SourceConfig.spec.ts @@ -0,0 +1,19 @@ +import {describe} from 'mocha' +import {expect} from 'chai' +import SourceConfig from "../../../Models/ThemeConfig/SourceConfig"; +import {TagUtils} from "../../../Logic/Tags/TagUtils"; + +describe("SourceConfig", () => { + + it("should throw an error on conflicting tags", () => { + expect(() => { + new SourceConfig( + { + osmTags: TagUtils.Tag({ + and: ["x=y", "a=b", "x!=y"] + }) + }, false + ) + }).to.throw(/tags are conflicting/) + }) +}) diff --git a/test/scripts/GenerateCache.spec.ts b/test/scripts/GenerateCache.spec.ts index e5be78431..51558bcd8 100644 --- a/test/scripts/GenerateCache.spec.ts +++ b/test/scripts/GenerateCache.spec.ts @@ -34,7 +34,7 @@ describe("GenerateCache", () => { } mkdirSync("/tmp/np-cache") initDownloads( - "(nwr%5B%22amenity%22%3D%22toilets%22%5D%3Bnwr%5B%22amenity%22%3D%22parking%22%5D%3Bnwr%5B%22amenity%22%3D%22bench%22%5D%3Bnwr%5B%22id%22%3D%22location_track%22%5D%3Bnwr%5B%22id%22%3D%22gps%22%5D%3Bnwr%5B%22information%22%3D%22board%22%5D%3Bnwr%5B%22leisure%22%3D%22picnic_table%22%5D%3Bnwr%5B%22man_made%22%3D%22watermill%22%5D%3Bnwr%5B%22user%3Ahome%22%3D%22yes%22%5D%3Bnwr%5B%22user%3Alocation%22%3D%22yes%22%5D%3Bnwr%5B%22leisure%22%3D%22nature_reserve%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22boundary%22%3D%22protected_area%22%5D%5B%22protect_class%22!~%22%5E98%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22information%22%3D%22visitor_centre%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22information%22%3D%22office%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*foot.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*hiking.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*bycicle.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*horse.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22leisure%22%3D%22bird_hide%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22amenity%22%3D%22drinking_water%22%5D%5B%22access%22!~%22%5Epermissive%24%22%5D%5B%22access%22!~%22%5Eprivate%24%22%5D%3B)%3Bout%20body%3Bout%20meta%3B%3E%3Bout%20skel%20qt%3B" + "(nwr%5B%22amenity%22%3D%22toilets%22%5D%3Bnwr%5B%22amenity%22%3D%22parking%22%5D%3Bnwr%5B%22amenity%22%3D%22bench%22%5D%3Bnwr%5B%22id%22%3D%22location_track%22%5D%3Bnwr%5B%22id%22%3D%22gps%22%5D%3Bnwr%5B%22information%22%3D%22board%22%5D%3Bnwr%5B%22leisure%22%3D%22picnic_table%22%5D%3Bnwr%5B%22man_made%22%3D%22watermill%22%5D%3Bnwr%5B%22user%3Ahome%22%3D%22yes%22%5D%3Bnwr%5B%22user%3Alocation%22%3D%22yes%22%5D%3Bnwr%5B%22leisure%22%3D%22nature_reserve%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22boundary%22%3D%22protected_area%22%5D%5B%22protect_class%22!%3D%2298%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22information%22%3D%22visitor_centre%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22information%22%3D%22office%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*foot.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*hiking.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*bycicle.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22route%22~%22%5E.*horse.*%24%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22leisure%22%3D%22bird_hide%22%5D%5B%22operator%22~%22%5E.*%5BnN%5Datuurpunt.*%24%22%5D%3Bnwr%5B%22amenity%22%3D%22drinking_water%22%5D%5B%22access%22!%3D%22permissive%22%5D%5B%22access%22!%3D%22private%22%5D%3B)%3Bout%20body%3Bout%20meta%3B%3E%3Bout%20skel%20qt%3B" ); await main([ "natuurpunt",