diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c01a70c5..7eb16a3e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,22 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.46.9](https://github.com/USERNAME/REPOSITORY_NAME/compare/v0.46.8...v0.46.9) (2024-09-14) + + +### Bug Fixes + +* fix [#2142](https://github.com/pietervdvn/MapComplete/issues/2142) ([f2fca2d](https://github.com/USERNAME/REPOSITORY_NAME/commitsf2fca2dad8576a18629591e886e511912c1d99e9)) +* nobrand= is actually applied when using the Name suggestion index ([c3bb0cb](https://github.com/USERNAME/REPOSITORY_NAME/commitsc3bb0cb83787c299ee4a92e8df6046aa448d77c8)) +* scroll horizontal images into view ([0397863](https://github.com/USERNAME/REPOSITORY_NAME/commits03978631ebd1e61abd13dd7a53bdb400c3d0f059)) +* some fixes to make studio useable again, probably fixes [#2139](https://github.com/pietervdvn/MapComplete/issues/2139) ([6672fc8](https://github.com/USERNAME/REPOSITORY_NAME/commits6672fc87b4326db65289dfa31599ec0583d6c0f4)) + + +### Theme improvements + +* **disaster_respone:** add a police station layer, add this and more layers to disaster_response theme ([418a4a7](https://github.com/USERNAME/REPOSITORY_NAME/commits418a4a71af5824487e4aa6754701e5d14371beae)) +* **disaster_response:** add defibrillators and logical zoom levels ([65fceb9](https://github.com/USERNAME/REPOSITORY_NAME/commits65fceb9434294051c8f565d89f42443c6afe3fb8)) + ### [0.46.8](https://github.com/USERNAME/REPOSITORY_NAME/compare/v0.46.7...v0.46.8) (2024-09-13) diff --git a/assets/layers/caravansites/caravansites.json b/assets/layers/caravansites/caravansites.json index 8964f3596..a0143f04f 100644 --- a/assets/layers/caravansites/caravansites.json +++ b/assets/layers/caravansites/caravansites.json @@ -21,7 +21,27 @@ "pl": "Miejsca kamperowe", "zh_Hans": "露营地" }, - "minzoom": 7, + "description": { + "en": "camper sites", + "it": "Aree camper", + "ru": "площадки для кемпинга", + "ja": "キャンプサイト", + "fr": "campings", + "zh_Hant": "露營地", + "nl": "camperplaatsen", + "pt_BR": "Locais de acampamento", + "de": "Wohnmobilstellplätze", + "hu": "Lakóautós megállóhelyek", + "id": "Tempat camping", + "ca": "llocs d'acampada", + "es": "Sitios de acampada", + "da": "autocamperpladser", + "pa_PK": "کیمب‌سائیٹاں", + "cs": "kempovací místa", + "eu": "Kanpatzeko tokiak", + "pl": "miejsca dla kamperów", + "zh_Hans": "露营地" + }, "source": { "osmTags": { "and": [ @@ -30,6 +50,7 @@ ] } }, + "minzoom": 7, "title": { "render": { "en": "Camper site {name}", @@ -77,27 +98,89 @@ } ] }, - "description": { - "en": "camper sites", - "it": "Aree camper", - "ru": "площадки для кемпинга", - "ja": "キャンプサイト", - "fr": "campings", - "zh_Hant": "露營地", - "nl": "camperplaatsen", - "pt_BR": "Locais de acampamento", - "de": "Wohnmobilstellplätze", - "hu": "Lakóautós megállóhelyek", - "id": "Tempat camping", - "ca": "llocs d'acampada", - "es": "Sitios de acampada", - "da": "autocamperpladser", - "pa_PK": "کیمب‌سائیٹاں", - "cs": "kempovací místa", - "eu": "Kanpatzeko tokiak", - "pl": "miejsca dla kamperów", - "zh_Hans": "露营地" - }, + "pointRendering": [ + { + "marker": [ + { + "icon": "circle", + "color": "white" + }, + { + "icon": { + "render": "./assets/themes/campersite/caravan.svg", + "mappings": [ + { + "if": { + "and": [ + "fee=no" + ] + }, + "then": "./assets/themes/campersite/caravan_green.svg" + } + ] + } + } + ], + "iconSize": "40,40", + "location": [ + "point", + "centroid" + ], + "anchor": "center" + } + ], + "lineRendering": [ + { + "color": "#00f", + "width": "8" + } + ], + "presets": [ + { + "tags": [ + "tourism=caravan_site" + ], + "title": { + "en": "a camper site", + "ru": "площадка для кемпинга", + "ja": "キャンプサイト", + "zh_Hant": "露營地", + "it": "una luogo di campeggio", + "fr": "une aire de camping", + "pt_BR": "uma local de acampamento", + "de": "ein Wohnmobilstellplatz", + "nl": "een camperplaats", + "hu": "lakóautós megállóhely", + "ca": "un lloc d'acampada", + "es": "Un camping", + "da": "en autocamperplads", + "pa_PK": "اِک کیمپ‌سائیٹ", + "cs": "kempovací místa", + "eu": "Kanpin bat", + "pl": "miejsce dla kampera", + "pt": "uma local de acampamento", + "zh_Hans": "露营地" + }, + "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 ", + "ru": "Добавьте новую официальную площадку для кемпинга. Это специально отведённые места для ночлега с автофургоном. Они могут выглядеть как настоящий кемпинг или просто выглядеть как парковка. Они не могут быть обозначены вообще, а просто быть определены в муниципальном решении. Обычная парковка, предназначенная для отдыхающих, где не ожидается, что они проведут ночь это -НЕ- площадка для кемпинга ", + "ja": "新しい公式キャンプサイトを追加します。お客様のキャンピングカーで一泊する指定の場所です。本物のキャンプのように見えるかもしれないし、単なる駐車場のように見えるかもしれない。それらは全く署名されていないかもしれませんが、自治体の決定で定義されているだけです。夜を過ごすことが予想されないキャンパー向けの通常の駐車場は、キャンプサイトではない ", + "it": "Aggiungi una nuova area di sosta ufficiale per camper. Si tratta di aree destinate alla sosta notturna dei camper. Potrebbe trattarsi di luoghi di campeggio o semplici parcheggi. Potrebbero anche non essere segnalati sul posto, ma semplicemente indicati in una delibera comunale. Un parcheggio destinato ai camper in cui non è però consentito trascorrere la notte -non- va considerato un'area di sosta per camper. ", + "fr": "Ajouter une nouvelle aire officielle pour campings-cars, destinée à y passer la nuit avec un camping-car. Elle ne nécessite pas d’infrastructures particulières et peut être simplement désignée sous arrêté municipal, un simple parking pour camping-cars non destiné au stationnement de nuit ne rentre pas dans cette catégorie ", + "de": "Fügen Sie einen neuen offiziellen Wohnmobilstellplatz hinzu. Dies sind ausgewiesene Plätze, an denen Sie in Ihrem Wohnmobil übernachten können. Sie können wie ein richtiger Campingplatz oder nur wie ein Parkplatz aussehen. Möglicherweise sind sie gar nicht ausgeschildert, sondern nur in einem Gemeindebeschluss festgelegt. Ein normaler Parkplatz für Wohnmobile, auf dem übernachten nicht zulässig ist, zählt nicht als 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. ", + "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. ", + "ca": "Afig un nou lloc d'acampada oficial. Són llocs designats per a passar la nit amb la teua caravana. Poden semblar-se a un càmping real o simplement a un aparcament. Pot ser que no estiguen senyalitzats en absolut, sinó que simplement estiguen definits per una decisió municipal. Un aparcament normal destinat als acampadors en el qual no s'espera que es passe la nit, no és un càmping. ", + "da": "Tilføj en ny officiel campingplads. Disse er udpegede steder at overnatte med din autocamper. De kan ligne en rigtig campingplads eller bare ligne en parkeringsplads. De er måske slet ikke skiltet, men er blot defineret i en kommunal beslutning. En almindelig parkering beregnet til campister, hvor det ikke forventes at overnatte, er -ikke- en autocamperplads ", + "cs": "Přidejte nové oficiální kempovací místo. Jedná se o místa, určená pro přenocování s karavanem. Mohou vypadat jako skutečný kemp nebo jen jako parkoviště. Takováto místa nemusí být označena, ale stačí, pokud jsou pouze definována v rozhodnutí obce. Běžné parkoviště určené pro táborníky, kde se nepovažuje za kempovací místo. ", + "eu": "Kanpaleku ofizialeko beste leku bat gehitu du. Gaua zure karabanarekin igarotzeko lekuak dira. Benetako kanpin baten edo, besterik gabe, aparkaleku baten itxura izan dezakete. Baliteke ez egotea inola ere seinaleztatuta, baizik eta udal erabaki batean definitzea. Kanpinlarientzako aparkaleku arrunt bat ez da kanpin bat, gaua bertan pasatzea espero ez bada ere. ", + "pl": "Dodaj nowe oficjalne miejsce dla kamperów. Są to wyznaczone miejsca, w których można przenocować w swoim kamperze. Mogą wyglądać jak prawdziwy kemping lub po prostu wyglądać jak parking. Mogą one w ogóle nie być oznakowane, a jedynie określone w decyzji gminy. Zwykły parking przeznaczony dla kamperów, na którym nie przewiduje się nocowania, nie jest miejscem dla kamperów ", + "zh_Hans": "添加一个新的官方露营车场地。这些是专门设置的供露营车过夜的地点。它们可能看起来像真正的露营地,也可能只是看起来像一个停车场。它们可能没有任何标识,仅在市政决策中定义。普通的停车场,尽管可能供露营车使用,但不期望在其中过夜的,不算作露营车场地 " + } + } + ], "tagRenderings": [ "images", { @@ -848,88 +931,5 @@ "questions", "reviews" ], - "presets": [ - { - "tags": [ - "tourism=caravan_site" - ], - "title": { - "en": "a camper site", - "ru": "площадка для кемпинга", - "ja": "キャンプサイト", - "zh_Hant": "露營地", - "it": "una luogo di campeggio", - "fr": "une aire de camping", - "pt_BR": "uma local de acampamento", - "de": "ein Wohnmobilstellplatz", - "nl": "een camperplaats", - "hu": "lakóautós megállóhely", - "ca": "un lloc d'acampada", - "es": "Un camping", - "da": "en autocamperplads", - "pa_PK": "اِک کیمپ‌سائیٹ", - "cs": "kempovací místa", - "eu": "Kanpin bat", - "pl": "miejsce dla kampera", - "pt": "uma local de acampamento", - "zh_Hans": "露营地" - }, - "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 ", - "ru": "Добавьте новую официальную площадку для кемпинга. Это специально отведённые места для ночлега с автофургоном. Они могут выглядеть как настоящий кемпинг или просто выглядеть как парковка. Они не могут быть обозначены вообще, а просто быть определены в муниципальном решении. Обычная парковка, предназначенная для отдыхающих, где не ожидается, что они проведут ночь это -НЕ- площадка для кемпинга ", - "ja": "新しい公式キャンプサイトを追加します。お客様のキャンピングカーで一泊する指定の場所です。本物のキャンプのように見えるかもしれないし、単なる駐車場のように見えるかもしれない。それらは全く署名されていないかもしれませんが、自治体の決定で定義されているだけです。夜を過ごすことが予想されないキャンパー向けの通常の駐車場は、キャンプサイトではない ", - "it": "Aggiungi una nuova area di sosta ufficiale per camper. Si tratta di aree destinate alla sosta notturna dei camper. Potrebbe trattarsi di luoghi di campeggio o semplici parcheggi. Potrebbero anche non essere segnalati sul posto, ma semplicemente indicati in una delibera comunale. Un parcheggio destinato ai camper in cui non è però consentito trascorrere la notte -non- va considerato un'area di sosta per camper. ", - "fr": "Ajouter une nouvelle aire officielle pour campings-cars, destinée à y passer la nuit avec un camping-car. Elle ne nécessite pas d’infrastructures particulières et peut être simplement désignée sous arrêté municipal, un simple parking pour camping-cars non destiné au stationnement de nuit ne rentre pas dans cette catégorie ", - "de": "Fügen Sie einen neuen offiziellen Wohnmobilstellplatz hinzu. Dies sind ausgewiesene Plätze, an denen Sie in Ihrem Wohnmobil übernachten können. Sie können wie ein richtiger Campingplatz oder nur wie ein Parkplatz aussehen. Möglicherweise sind sie gar nicht ausgeschildert, sondern nur in einem Gemeindebeschluss festgelegt. Ein normaler Parkplatz für Wohnmobile, auf dem übernachten nicht zulässig ist, zählt nicht als 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. ", - "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. ", - "ca": "Afig un nou lloc d'acampada oficial. Són llocs designats per a passar la nit amb la teua caravana. Poden semblar-se a un càmping real o simplement a un aparcament. Pot ser que no estiguen senyalitzats en absolut, sinó que simplement estiguen definits per una decisió municipal. Un aparcament normal destinat als acampadors en el qual no s'espera que es passe la nit, no és un càmping. ", - "da": "Tilføj en ny officiel campingplads. Disse er udpegede steder at overnatte med din autocamper. De kan ligne en rigtig campingplads eller bare ligne en parkeringsplads. De er måske slet ikke skiltet, men er blot defineret i en kommunal beslutning. En almindelig parkering beregnet til campister, hvor det ikke forventes at overnatte, er -ikke- en autocamperplads ", - "cs": "Přidejte nové oficiální kempovací místo. Jedná se o místa, určená pro přenocování s karavanem. Mohou vypadat jako skutečný kemp nebo jen jako parkoviště. Takováto místa nemusí být označena, ale stačí, pokud jsou pouze definována v rozhodnutí obce. Běžné parkoviště určené pro táborníky, kde se nepovažuje za kempovací místo. ", - "eu": "Kanpaleku ofizialeko beste leku bat gehitu du. Gaua zure karabanarekin igarotzeko lekuak dira. Benetako kanpin baten edo, besterik gabe, aparkaleku baten itxura izan dezakete. Baliteke ez egotea inola ere seinaleztatuta, baizik eta udal erabaki batean definitzea. Kanpinlarientzako aparkaleku arrunt bat ez da kanpin bat, gaua bertan pasatzea espero ez bada ere. ", - "pl": "Dodaj nowe oficjalne miejsce dla kamperów. Są to wyznaczone miejsca, w których można przenocować w swoim kamperze. Mogą wyglądać jak prawdziwy kemping lub po prostu wyglądać jak parking. Mogą one w ogóle nie być oznakowane, a jedynie określone w decyzji gminy. Zwykły parking przeznaczony dla kamperów, na którym nie przewiduje się nocowania, nie jest miejscem dla kamperów ", - "zh_Hans": "添加一个新的官方露营车场地。这些是专门设置的供露营车过夜的地点。它们可能看起来像真正的露营地,也可能只是看起来像一个停车场。它们可能没有任何标识,仅在市政决策中定义。普通的停车场,尽管可能供露营车使用,但不期望在其中过夜的,不算作露营车场地 " - } - } - ], - "pointRendering": [ - { - "marker": [ - { - "icon": "circle", - "color": "white" - }, - { - "icon": { - "render": "./assets/themes/campersite/caravan.svg", - "mappings": [ - { - "if": { - "and": [ - "fee=no" - ] - }, - "then": "./assets/themes/campersite/caravan_green.svg" - } - ] - } - } - ], - "iconSize": "40,40", - "location": [ - "point", - "centroid" - ], - "anchor": "center" - } - ], - "lineRendering": [ - { - "color": "#00f", - "width": "8" - } - ], "allowMove": true } diff --git a/assets/layers/charging_station/charging_station.json b/assets/layers/charging_station/charging_station.json index 1d5bccb6d..132a6710e 100644 --- a/assets/layers/charging_station/charging_station.json +++ b/assets/layers/charging_station/charging_station.json @@ -5,7 +5,13 @@ "nl": "Oplaadpunten", "de": "Ladestationen" }, - "minzoom": 10, + "description": { + "en": "A charging station", + "nl": "Oplaadpunten", + "ca": "Una estació de càrrega", + "de": "Eine Ladestation", + "fr": "Une station de recharge" + }, "source": { "osmTags": { "and": [ @@ -20,6 +26,7 @@ ] } }, + "minzoom": 10, "title": { "render": { "en": "Charging station", @@ -65,14 +72,109 @@ } ] }, - "description": { - "en": "A charging station", - "nl": "Oplaadpunten", - "ca": "Una estació de càrrega", - "de": "Eine Ladestation", - "fr": "Une station de recharge" - }, - "#": "no-question-hint-check", + "pointRendering": [ + { + "location": [ + "point", + "centroid" + ], + "marker": [ + { + "icon": "pin", + "color": "#fff" + }, + { + "icon": { + "render": "./assets/themes/charging_stations/plug.svg", + "mappings": [ + { + "if": "bicycle=yes", + "then": "./assets/themes/charging_stations/bicycle.svg" + }, + { + "if": { + "or": [ + "car=yes", + "motorcar=yes" + ] + }, + "then": "./assets/themes/charging_stations/car.svg" + } + ] + } + } + ], + "iconBadges": [ + { + "if": { + "or": [ + "disused:amenity=charging_station", + "operational_status=broken" + ] + }, + "then": "close:#c22;" + }, + { + "if": { + "or": [ + "proposed:amenity=charging_station", + "planned:amenity=charging_station" + ] + }, + "then": "./assets/layers/charging_station/under_construction.svg" + }, + { + "if": { + "and": [ + "bicycle=yes", + { + "or": [ + "motorcar=yes", + "car=yes" + ] + } + ] + }, + "then": "circle:#fff;./assets/themes/charging_stations/car.svg" + } + ], + "anchor": "bottom", + "iconSize": "50,50" + } + ], + "lineRendering": [ + { + "color": "black", + "width": 2, + "fillColor": "#80808080" + } + ], + "presets": [ + { + "tags": [ + "amenity=charging_station", + "motorcar=no", + "bicycle=yes" + ], + "title": { + "en": "charging station for electrical bikes", + "nl": "oplaadpunt voor elektrische fietsen", + "de": "Ladestation für Elektrofahrräder" + } + }, + { + "tags": [ + "amenity=charging_station", + "motorcar=yes", + "bicycle=no" + ], + "title": { + "en": "charging station for cars", + "nl": "oplaadstation voor elektrische auto's", + "de": "Ladestation für Autos" + } + } + ], "tagRenderings": [ "images", { @@ -2778,109 +2880,6 @@ } } ], - "lineRendering": [ - { - "color": "black", - "width": 2, - "fillColor": "#80808080" - } - ], - "pointRendering": [ - { - "location": [ - "point", - "centroid" - ], - "marker": [ - { - "icon": "pin", - "color": "#fff" - }, - { - "icon": { - "render": "./assets/themes/charging_stations/plug.svg", - "mappings": [ - { - "if": "bicycle=yes", - "then": "./assets/themes/charging_stations/bicycle.svg" - }, - { - "if": { - "or": [ - "car=yes", - "motorcar=yes" - ] - }, - "then": "./assets/themes/charging_stations/car.svg" - } - ] - } - } - ], - "iconBadges": [ - { - "if": { - "or": [ - "disused:amenity=charging_station", - "operational_status=broken" - ] - }, - "then": "close:#c22;" - }, - { - "if": { - "or": [ - "proposed:amenity=charging_station", - "planned:amenity=charging_station" - ] - }, - "then": "./assets/layers/charging_station/under_construction.svg" - }, - { - "if": { - "and": [ - "bicycle=yes", - { - "or": [ - "motorcar=yes", - "car=yes" - ] - } - ] - }, - "then": "circle:#fff;./assets/themes/charging_stations/car.svg" - } - ], - "anchor": "bottom", - "iconSize": "50,50" - } - ], - "presets": [ - { - "tags": [ - "amenity=charging_station", - "motorcar=no", - "bicycle=yes" - ], - "title": { - "en": "charging station for electrical bikes", - "nl": "oplaadpunt voor elektrische fietsen", - "de": "Ladestation für Elektrofahrräder" - } - }, - { - "tags": [ - "amenity=charging_station", - "motorcar=yes", - "bicycle=no" - ], - "title": { - "en": "charging station for cars", - "nl": "oplaadstation voor elektrische auto's", - "de": "Ladestation für Autos" - } - } - ], "filter": [ { "id": "vehicle-type", @@ -3128,6 +3127,19 @@ ] } ], + "deletion": { + "softDeletionTags": { + "and": [ + "amenity=", + "disused:amenity=charging_station" + ] + }, + "neededChangesets": 10 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuracy": true + }, "units": [ { "maxstay": { @@ -3322,17 +3334,5 @@ } } ], - "allowMove": { - "enableRelocation": false, - "enableImproveAccuracy": true - }, - "deletion": { - "softDeletionTags": { - "and": [ - "amenity=", - "disused:amenity=charging_station" - ] - }, - "neededChangesets": 10 - } -} \ No newline at end of file + "#": "no-question-hint-check" +} diff --git a/assets/layers/climbing_opportunity/climbing_opportunity.json b/assets/layers/climbing_opportunity/climbing_opportunity.json index b25ca2c69..031ec13a8 100644 --- a/assets/layers/climbing_opportunity/climbing_opportunity.json +++ b/assets/layers/climbing_opportunity/climbing_opportunity.json @@ -34,9 +34,6 @@ ] } }, - "snapName": { - "en": "a wall, cliff or rock" - }, "minzoom": 18, "title": { "render": { @@ -152,5 +149,8 @@ } ], "allowMove": false, + "snapName": { + "en": "a wall, cliff or rock" + }, "doCount": false } diff --git a/assets/layers/cycleways_and_roads/cycleways_and_roads.json b/assets/layers/cycleways_and_roads/cycleways_and_roads.json index 61337d9a5..27d669d2e 100644 --- a/assets/layers/cycleways_and_roads/cycleways_and_roads.json +++ b/assets/layers/cycleways_and_roads/cycleways_and_roads.json @@ -9,10 +9,6 @@ "ca": "Vies ciclistes i carreteres", "cs": "Cyklostezky a silnice" }, - "snapName": { - "en": "a road or a cycleway", - "nl": "een weg, straat of fietspad" - }, "description": { "en": "All infrastructure that someone can cycle over, accompanied with questions about this infrastructure", "nl": "Alle infrastructuur waar je over kunt fietsen, met vragen over die infrastructuur", @@ -1917,5 +1913,9 @@ } ], "allowMove": false, - "allowSplit": true + "allowSplit": true, + "snapName": { + "en": "a road or a cycleway", + "nl": "een weg, straat of fietspad" + } } diff --git a/assets/layers/dumpstations/dumpstations.json b/assets/layers/dumpstations/dumpstations.json index 66003ad53..bd4f3cf87 100644 --- a/assets/layers/dumpstations/dumpstations.json +++ b/assets/layers/dumpstations/dumpstations.json @@ -18,7 +18,24 @@ "pl": "Stacje zrzutów sanitarnych", "pt": "Estações de despejo sanitário" }, - "minzoom": 7, + "description": { + "en": "Sanitary dump stations", + "ru": "Ассенизационные сливные станции", + "ja": "衛生ゴミ捨て場", + "it": "Luoghi di sversamento delle acque reflue", + "fr": "Site de vidange sanitaire", + "pt_BR": "Estações de despejo sanitário", + "de": "Sanitäre Entsorgungsstationen", + "zh_Hant": "垃圾處理站", + "id": "Tempat pembuangan sanitasi", + "nl": "Loosplaatsen", + "ca": "Estacions d'abocament sanitari", + "da": "Sanitære afleveringspladser", + "cs": "Sanitární skládky", + "es": "Vertederos Sanitarios", + "pl": "Stacje zrzutów sanitarnych", + "pt": "Estações de despejo sanitário" + }, "source": { "osmTags": { "and": [ @@ -27,6 +44,7 @@ ] } }, + "minzoom": 7, "title": { "render": { "en": "Dump station {name}", @@ -70,24 +88,66 @@ } ] }, - "description": { - "en": "Sanitary dump stations", - "ru": "Ассенизационные сливные станции", - "ja": "衛生ゴミ捨て場", - "it": "Luoghi di sversamento delle acque reflue", - "fr": "Site de vidange sanitaire", - "pt_BR": "Estações de despejo sanitário", - "de": "Sanitäre Entsorgungsstationen", - "zh_Hant": "垃圾處理站", - "id": "Tempat pembuangan sanitasi", - "nl": "Loosplaatsen", - "ca": "Estacions d'abocament sanitari", - "da": "Sanitære afleveringspladser", - "cs": "Sanitární skládky", - "es": "Vertederos Sanitarios", - "pl": "Stacje zrzutów sanitarnych", - "pt": "Estações de despejo sanitário" - }, + "pointRendering": [ + { + "marker": [ + { + "icon": "circle", + "color": "white" + }, + { + "icon": "./assets/themes/campersite/sanitary_dump_station.svg" + } + ], + "iconSize": "32,32", + "location": [ + "point" + ], + "anchor": "center" + } + ], + "lineRendering": [ + { + "color": "#00f", + "width": "8" + } + ], + "presets": [ + { + "tags": [ + "amenity=sanitary_dump_station" + ], + "title": { + "en": "a sanitary dump station", + "ja": "衛生ゴミ捨て場", + "it": "una luogo di sversamento delle acque reflue", + "fr": "une site de vidange", + "de": "eine sanitäre Entsorgungsstation", + "zh_Hant": "垃圾丟棄站", + "nl": "een loosplaats", + "da": "en sanitær afleveringsplads", + "ca": "una estació d'abocament sanitari", + "cs": "sanitární skládka", + "es": "un vertedero sanitario", + "pl": "stacja zrzutu sanitarnego" + }, + "description": { + "en": "Add a new sanitary dump station. This is a place where camper drivers can dump waste water or chemical toilet waste. Often there's also drinking water and electricity.", + "ja": "新しい衛生ゴミ捨て場を追加します。ここは、キャンピングカーの運転手が排水や携帯トイレの廃棄物を捨てることができる場所です。飲料水や電気もあることが多いです。", + "it": "Aggiungi un nuovo luogo di sversamento delle acque reflue. Si tratta di luoghi dove chi viaggia in camper può smaltire le acque grigie o le acque nere. Spesso forniscono anche acqua ed elettricità.", + "fr": "Ajouter un nouveau site de vidange. Un espace où évacuer ses eaux usées (grises et/ou noires). Généralement alimenté en eau potable et électricité.", + "de": "Fügen Sie eine neue sanitäre Entsorgungsstation hinzu. Hier können Camper Abwasser oder chemischen Toilettenabfälle entsorgen. Oft gibt es auch Trinkwasser und Strom.", + "zh_Hant": "新增垃圾站,這通常是提供露營駕駛丟棄廢水與化學性廁所廢水的地方,也會有飲用水與電力。", + "hu": "Új egészségügyihulldék-lerakó hozzáadása. Ez egy olyan hely, ahol a lakókocsisok a szennyvizet vagy a vegyi WC hulladékát kiüríthetik. Gyakran van ivóvíz és áram is.", + "nl": "Voeg een nieuwe loosplaats toe. Dat is een plaats waar campers hun grijs water en toiletten kunnen lozen. Vaak is er ook een kraan om water te tanken en een stopcontact.", + "da": "Tilføj en ny sanitær afleveringsplads. Dette er et sted, hvor autocamperchauffører kan dumpe spildevand eller kemisk toiletaffald. Ofte er der også drikkevand og el.", + "cs": "Přidejte novou sanitární skládku. Toto je místo, kam mohou řidiči obytných vozů vypouštět odpadní vodu nebo odpad z chemických toalet. Často je zde také dostupná pitná voda a elektřina.", + "es": "Añadir un nuevo vertedero sanitario. Se trata de un lugar donde los autocaravanistas pueden verter las aguas residuales o los residuos químicos de los aseos. A menudo también hay agua potable y electricidad.", + "ca": "Afegir una nova estació d'abocador sanitari. Aquest és un lloc on els conductors de campers poden abocar aigües residuals o residus de vàter químic. Sovint també hi ha aigua potable i electricitat.", + "pl": "Dodaj nową stację zrzutu sanitarnego. To miejsce, w którym kierowcy kamperów mogą wyrzucać ścieki lub odpady z toalet chemicznych. Często jest tam też woda pitna i prąd." + } + } + ], "tagRenderings": [ "images", { @@ -569,66 +629,6 @@ "id": "dumpstations-network" } ], - "presets": [ - { - "tags": [ - "amenity=sanitary_dump_station" - ], - "title": { - "en": "a sanitary dump station", - "ja": "衛生ゴミ捨て場", - "it": "una luogo di sversamento delle acque reflue", - "fr": "une site de vidange", - "de": "eine sanitäre Entsorgungsstation", - "zh_Hant": "垃圾丟棄站", - "nl": "een loosplaats", - "da": "en sanitær afleveringsplads", - "ca": "una estació d'abocament sanitari", - "cs": "sanitární skládka", - "es": "un vertedero sanitario", - "pl": "stacja zrzutu sanitarnego" - }, - "description": { - "en": "Add a new sanitary dump station. This is a place where camper drivers can dump waste water or chemical toilet waste. Often there's also drinking water and electricity.", - "ja": "新しい衛生ゴミ捨て場を追加します。ここは、キャンピングカーの運転手が排水や携帯トイレの廃棄物を捨てることができる場所です。飲料水や電気もあることが多いです。", - "it": "Aggiungi un nuovo luogo di sversamento delle acque reflue. Si tratta di luoghi dove chi viaggia in camper può smaltire le acque grigie o le acque nere. Spesso forniscono anche acqua ed elettricità.", - "fr": "Ajouter un nouveau site de vidange. Un espace où évacuer ses eaux usées (grises et/ou noires). Généralement alimenté en eau potable et électricité.", - "de": "Fügen Sie eine neue sanitäre Entsorgungsstation hinzu. Hier können Camper Abwasser oder chemischen Toilettenabfälle entsorgen. Oft gibt es auch Trinkwasser und Strom.", - "zh_Hant": "新增垃圾站,這通常是提供露營駕駛丟棄廢水與化學性廁所廢水的地方,也會有飲用水與電力。", - "hu": "Új egészségügyihulldék-lerakó hozzáadása. Ez egy olyan hely, ahol a lakókocsisok a szennyvizet vagy a vegyi WC hulladékát kiüríthetik. Gyakran van ivóvíz és áram is.", - "nl": "Voeg een nieuwe loosplaats toe. Dat is een plaats waar campers hun grijs water en toiletten kunnen lozen. Vaak is er ook een kraan om water te tanken en een stopcontact.", - "da": "Tilføj en ny sanitær afleveringsplads. Dette er et sted, hvor autocamperchauffører kan dumpe spildevand eller kemisk toiletaffald. Ofte er der også drikkevand og el.", - "cs": "Přidejte novou sanitární skládku. Toto je místo, kam mohou řidiči obytných vozů vypouštět odpadní vodu nebo odpad z chemických toalet. Často je zde také dostupná pitná voda a elektřina.", - "es": "Añadir un nuevo vertedero sanitario. Se trata de un lugar donde los autocaravanistas pueden verter las aguas residuales o los residuos químicos de los aseos. A menudo también hay agua potable y electricidad.", - "ca": "Afegir una nova estació d'abocador sanitari. Aquest és un lloc on els conductors de campers poden abocar aigües residuals o residus de vàter químic. Sovint també hi ha aigua potable i electricitat.", - "pl": "Dodaj nową stację zrzutu sanitarnego. To miejsce, w którym kierowcy kamperów mogą wyrzucać ścieki lub odpady z toalet chemicznych. Często jest tam też woda pitna i prąd." - } - } - ], - "pointRendering": [ - { - "marker": [ - { - "icon": "circle", - "color": "white" - }, - { - "icon": "./assets/themes/campersite/sanitary_dump_station.svg" - } - ], - "iconSize": "32,32", - "location": [ - "point" - ], - "anchor": "center" - } - ], - "lineRendering": [ - { - "color": "#00f", - "width": "8" - } - ], "allowMove": { "enableImproveAccuracy": true, "enableRelocation": false diff --git a/assets/layers/geocoded_image/geocoded_image.json b/assets/layers/geocoded_image/geocoded_image.json index c5a9d8b13..dd6f57efd 100644 --- a/assets/layers/geocoded_image/geocoded_image.json +++ b/assets/layers/geocoded_image/geocoded_image.json @@ -1,8 +1,7 @@ { "id": "geocoded_image", - "source": "special", "name": null, - "tagRenderings": [], + "source": "special", "pointRendering": [ { "location": [ @@ -66,5 +65,6 @@ ], "iconSize": "14,14" } - ] + ], + "tagRenderings": [] } diff --git a/assets/layers/indoors/indoors.json b/assets/layers/indoors/indoors.json index 9d4c7abfc..3ef29d1ba 100644 --- a/assets/layers/indoors/indoors.json +++ b/assets/layers/indoors/indoors.json @@ -8,10 +8,6 @@ "ca": "Interiors", "cs": "Vnitřní prostory" }, - "snapName": { - "en": "an indoor wall", - "nl": "een binnenmuur" - }, "description": { "en": "Basic indoor mapping: shows room outlines", "de": "Grundlegende Innenraumkartierung: zeigt Umrisse von Räumen", @@ -623,5 +619,9 @@ "allowMove": { "enableImproveAccuracy": true, "enableRelocation": false + }, + "snapName": { + "en": "an indoor wall", + "nl": "een binnenmuur" } } diff --git a/assets/layers/kerbs/kerbs.json b/assets/layers/kerbs/kerbs.json index b10bc4061..51614d02b 100644 --- a/assets/layers/kerbs/kerbs.json +++ b/assets/layers/kerbs/kerbs.json @@ -11,9 +11,6 @@ "ca": "Vroades", "cs": "Obrubníky" }, - "snapName": { - "en": "a kerb" - }, "description": { "en": "A layer showing kerbs.", "nl": "Een laag met stoepranden.", @@ -409,5 +406,8 @@ ] } } - ] + ], + "snapName": { + "en": "a kerb" + } } diff --git a/assets/layers/note/note.json b/assets/layers/note/note.json index 9405256f8..39e251fec 100644 --- a/assets/layers/note/note.json +++ b/assets/layers/note/note.json @@ -291,6 +291,23 @@ } ] }, + { + "id": "search_not_any", + "options": [ + { + "osmTags": "_all_comments!~i~.*{search}.*", + "fields": [ + { + "name": "search" + } + ], + "question": { + "en": "Should not mention {search} in any comment" + } + } + ] + }, + { "id": "opened_by", "options": [ diff --git a/assets/layers/pedestrian_path/pedestrian_path.json b/assets/layers/pedestrian_path/pedestrian_path.json index ac8ccef8c..007ff1411 100644 --- a/assets/layers/pedestrian_path/pedestrian_path.json +++ b/assets/layers/pedestrian_path/pedestrian_path.json @@ -8,9 +8,6 @@ "ca": "Camins per a vianants", "cs": "Cesty pro chodce" }, - "snapName": { - "en": "a pedestrian path" - }, "description": { "en": "Pedestrian footpaths, especially used for indoor navigation and snapping entrances to this layer", "nl": "Pad voor voetgangers, in het bijzonder gebruikt voor navigatie binnen gebouwen en om aan toegangen vast te klikken in deze laag", @@ -49,5 +46,8 @@ "dashArray": "12 6" } ], - "allowMove": false + "allowMove": false, + "snapName": { + "en": "a pedestrian path" + } } diff --git a/assets/layers/police/license_info.json b/assets/layers/police/license_info.json new file mode 100644 index 000000000..e1d743c53 --- /dev/null +++ b/assets/layers/police/license_info.json @@ -0,0 +1,12 @@ +[ + { + "path": "police.svg", + "license": "CC-BY 4.0", + "authors": [ + "Twemoji" + ], + "sources": [ + "https://commons.wikimedia.org/wiki/File:Twemoji12_1f693.svg" + ] + } +] \ No newline at end of file diff --git a/assets/layers/police/police.json b/assets/layers/police/police.json new file mode 100644 index 000000000..a79631991 --- /dev/null +++ b/assets/layers/police/police.json @@ -0,0 +1,142 @@ +{ + "id": "police", + "name": { + "en": "Police stations" + }, + "description": { + "en": "Many types of police facilities " + }, + "source": { + "osmTags": { + "or": [ + "amenity=police", + "police~*" + ] + } + }, + "minzoom": 10, + "title": { + "render": { + "en": "{name}" + } + }, + "pointRendering": [ + { + "location": [ + "point", + "centroid" + ], + "marker": [ + { + "icon": "circle", + "color": "#00000000" + }, + { + "icon": "./assets/layers/police/police.svg" + } + ] + } + ], + "lineRendering": [ + { + "width": 1, + "color": "blue" + } + ], + "presets": [ + { + "tags": [ + "amenity=police" + ], + "title": { + "en": "a police office" + }, + "description": { + "en": "A police office where the general public can enter for inquiries" + } + }, + { + "tags": [ + "police=checkpoint" + ], + "title": { + "en": "a police checkpoint" + }, + "description": { + "en": "A place where police performs checks on travelling people" + } + }, + { + "tags": [ + "police=offices" + ], + "title": { + "en": "an administrative, police backoffice" + }, + "description": { + "en": "An administrative police office without services for the general public." + } + }, + { + "tags": [ + "police=detention" + ], + "title": "a police detention center", + "description": { + "en": "A jail run by the police without public services. People are detained here for a short time (at most a few days), e.g. for small misdemeanors, disturbance of the public order or awaiting a trial" + } + }, + { + "tags": [ + "police=naval_base" + ], + "title": "a police naval base", + "description": { + "en": "A naval or maritime base for the maritime police; often with a pier and police boats nearby" + } + } + ], + "tagRenderings": [ + "images", + "reviews", + { + "question": { + "en": "What is the name of this police facility?" + }, + "id": "police_name", + "render": { + "en": "{name}" + }, + "freeform": { + "key": "name" + } + }, + "{preset_type_select()}", + "contact", + "opening_hours", + { + "question": { + "en": "Does this police office have detention facilities?" + }, + "id": "4_z2nrdhy6tyyh4fd", + "condition": "amenity=police", + "mappings": [ + { + "if": "detention=yes", + "then": { + "en": "This police office has some cells to detain people" + } + }, + { + "if": "detention=no", + "then": { + "en": "This police office does not have cells to detain people" + } + } + ] + } + ], + "deletion": true, + "allowMove": true, + "enableMorePrivacy": true +} diff --git a/assets/layers/police/police.svg b/assets/layers/police/police.svg new file mode 100644 index 000000000..cbf344d7c --- /dev/null +++ b/assets/layers/police/police.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/layers/police/police.svg.license b/assets/layers/police/police.svg.license new file mode 100644 index 000000000..77a8edb48 --- /dev/null +++ b/assets/layers/police/police.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Twemoji +SPDX-License-Identifier: CC-BY 4.0 \ No newline at end of file diff --git a/assets/layers/recycling/recycling.json b/assets/layers/recycling/recycling.json index e2e4eb522..ccc12a897 100644 --- a/assets/layers/recycling/recycling.json +++ b/assets/layers/recycling/recycling.json @@ -1380,6 +1380,17 @@ ], "filter": [ "open_now", + { + "id": "centres_only", + "options": [ + { + "osmTags": "recycling_type=centre", + "question": { + "en": "Recycling centre" + } + } + ] + }, { "id": "recyclingType", "options": [ diff --git a/assets/layers/shelter/shelter.json b/assets/layers/shelter/shelter.json index 26361dc07..8b7f169be 100644 --- a/assets/layers/shelter/shelter.json +++ b/assets/layers/shelter/shelter.json @@ -8,9 +8,6 @@ "fr": "Abri", "cs": "Přístřešek" }, - "snapName": { - "en": "a shelter" - }, "description": { "en": "Layer showing shelter structures", "de": "Eine Ebene, die verschiedene Bauformen von Unterständen zeigt", @@ -128,5 +125,8 @@ "allowMove": { "enableRelocation": false, "enableImproveAccuracy": true + }, + "snapName": { + "en": "a shelter" } } diff --git a/assets/layers/walls_and_buildings/walls_and_buildings.json b/assets/layers/walls_and_buildings/walls_and_buildings.json index d1e62cbfa..9e41a19b1 100644 --- a/assets/layers/walls_and_buildings/walls_and_buildings.json +++ b/assets/layers/walls_and_buildings/walls_and_buildings.json @@ -12,10 +12,6 @@ "zh_Hant": "特殊的內建圖層顯示所有牆壁與建築。這個圖層對於規畫要靠牆的東西 (例如 AED、郵筒、入口、地址、監視器等) 相當實用。這個圖層預設顯示而且無法由使用者開關。", "pl": "Specjalna warstwa zabudowana zapewniająca wszystkie mury i budynki. Warstwa ta jest przydatna w ustawieniach wstępnych obiektów, które można umieścić przy ścianach (np. AED, skrzynki pocztowe, wejścia, adresy, kamery monitorujące itp.). Warstwa ta jest domyślnie niewidoczna i użytkownik nie może jej przełączać." }, - "snapName": { - "en": "a wall or building", - "nl": "een muur of gebouw" - }, "source": { "osmTags": { "or": [ @@ -144,5 +140,9 @@ ] } } - ] + ], + "snapName": { + "en": "a wall or building", + "nl": "een muur of gebouw" + } } diff --git a/assets/themes/disaster_response/disaster_response.json b/assets/themes/disaster_response/disaster_response.json index 23ba39a20..70bdc00f3 100644 --- a/assets/themes/disaster_response/disaster_response.json +++ b/assets/themes/disaster_response/disaster_response.json @@ -17,9 +17,38 @@ "icon": "./assets/themes/disaster_response/CivilDefence.svg", "socialImage": "./assets/themes/disaster_response/social.svg", "layers": [ - "hospital", - "assembly_point", - "disaster_response" + { + "builtin": [ + "hospital", + "fire_station", + "disaster_response", + "police" + ], + "override": { + "minzoom": 6 + } + }, + { + "builtin": [ + "extinguisher", + "assembly_point", + "defibrillator", + "hydrant" + ], + "override": { + "minzoom": 15 + } + }, + { + "builtin": [ + "doctors", + "ambulancestation", + "pharmacy" + ], + "override": { + "minzoom": 14 + } + } ], "docs": "https://wiki.openstreetmap.org/wiki/Emergency_facilities_and_amenities" -} \ No newline at end of file +} diff --git a/assets/themes/mapcomplete-changes/mapcomplete-changes.json b/assets/themes/mapcomplete-changes/mapcomplete-changes.json index 7873f6b66..67501aaef 100644 --- a/assets/themes/mapcomplete-changes/mapcomplete-changes.json +++ b/assets/themes/mapcomplete-changes/mapcomplete-changes.json @@ -1,13 +1,18 @@ { "id": "mapcomplete-changes", "title": { - "en": "Changes made with MapComplete" + "en": "Changes made with MapComplete", + "de": "Änderungen mit MapComplete" }, "shortDescription": { - "en": "Shows changes made by MapComplete" + "en": "Shows changes made by MapComplete", + "de": "Zeigt die von MapComplete vorgenommenen Änderungen an" }, "description": { - "en": "This maps shows all the changes made with MapComplete" + "en": "This maps shows all the changes made with MapComplete", + "de": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen", + "es": "Este mapa muestra todos los cambios realizados con MapComplete", + "pl": "Ta mapa pokazuje wszystkie zmiany wprowadzone za pomocą MapComplete" }, "icon": "./assets/svg/logo.svg", "hideFromOverview": true, @@ -18,7 +23,8 @@ { "id": "mapcomplete-changes", "name": { - "en": "Changeset centers" + "en": "Changeset centers", + "de": "Changeset-Zentren" }, "minzoom": 0, "source": { @@ -28,41 +34,49 @@ }, "title": { "render": { - "en": "Changeset for {theme}" + "en": "Changeset for {theme}", + "de": "Änderungssatz für {theme}" } }, "description": { - "en": "Shows all MapComplete changes" + "en": "Shows all MapComplete changes", + "de": "Zeigt alle MapComplete-Änderungen", + "es": "Muestra todos los cambios de MapComplete" }, "tagRenderings": [ { "id": "show_changeset_id", "render": { - "en": "Changeset {id}" + "en": "Changeset {id}", + "de": "Änderungssatz {id}" } }, { "id": "contributor", "question": { - "en": "What contributor did make this change?" + "en": "What contributor did make this change?", + "de": "Wer hat zu dieser Änderung beigetragen?" }, "freeform": { "key": "user" }, "render": { - "en": "Change made by {user}" + "en": "Change made by {user}", + "de": "Änderung vorgenommen von {user}" } }, { "id": "theme-id", "question": { - "en": "What theme was used to make this change?" + "en": "What theme was used to make this change?", + "de": "Welches Thema wurde für diese Änderung verwendet?" }, "freeform": { "key": "theme" }, "render": { - "en": "Change with theme {theme}" + "en": "Change with theme {theme}", + "de": "Änderung mit Thema {theme}" } }, { @@ -71,19 +85,23 @@ "key": "locale" }, "question": { - "en": "What locale (language) was this change made in?" + "en": "What locale (language) was this change made in?", + "de": "In welcher Sprache (Locale) wurde diese Änderung vorgenommen?" }, "render": { - "en": "User locale is {locale}" + "en": "User locale is {locale}", + "de": "Die Benutzersprache ist {locale}" } }, { "id": "host", "render": { - "en": "Change with with {host}" + "en": "Change with with {host}", + "de": "Änderung mit {host}" }, "question": { - "en": "What host (website) was this change made with?" + "en": "What host (website) was this change made with?", + "de": "Bei welchem Host (Website) wurde diese Änderung vorgenommen?" }, "freeform": { "key": "host" @@ -104,10 +122,12 @@ { "id": "version", "question": { - "en": "What version of MapComplete was used to make this change?" + "en": "What version of MapComplete was used to make this change?", + "de": "Welche Version von MapComplete wurde verwendet, um diese Änderung vorzunehmen?" }, "render": { - "en": "Made with {editor}" + "en": "Made with {editor}", + "de": "Erstellt mit {editor}" }, "freeform": { "key": "editor" @@ -505,7 +525,10 @@ } ], "question": { - "en": "Themename contains {search}" + "en": "Themename contains {search}", + "de": "Themenname enthält {search}", + "es": "El nombre contiene {search}", + "pl": "Nazwa tematu zawiera {search}" } } ] @@ -521,7 +544,9 @@ } ], "question": { - "en": "Themename does not contain {search}" + "en": "Themename does not contain {search}", + "de": "Themename enthält nicht {search}", + "es": "El nombre del tema no contiene {search}" } } ] @@ -537,7 +562,9 @@ } ], "question": { - "en": "Made by contributor {search}" + "en": "Made by contributor {search}", + "de": "Erstellt von Mitwirkendem {search}", + "es": "Hecho por el colaborador {search}" } } ] @@ -553,7 +580,9 @@ } ], "question": { - "en": "Not made by contributor {search}" + "en": "Not made by contributor {search}", + "de": "Nicht erstellt von Mitwirkendem {search}", + "es": "No realizado por el colaborador {search}" } } ] @@ -570,7 +599,9 @@ } ], "question": { - "en": "Made before {search}" + "en": "Made before {search}", + "de": "Erstellt vor {search}", + "es": "Realizado antes de {search}" } } ] @@ -587,7 +618,9 @@ } ], "question": { - "en": "Made after {search}" + "en": "Made after {search}", + "de": "Erstellt nach {search}", + "es": "Realizado después de {search}" } } ] @@ -603,7 +636,9 @@ } ], "question": { - "en": "User language (iso-code) {search}" + "en": "User language (iso-code) {search}", + "de": "Benutzersprache (ISO-Code) {search}", + "es": "Idioma del usuario (código iso) {search}" } } ] @@ -619,7 +654,8 @@ } ], "question": { - "en": "Made with host {search}" + "en": "Made with host {search}", + "de": "Erstellt mit Host {search}" } } ] @@ -630,7 +666,8 @@ { "osmTags": "add-image>0", "question": { - "en": "Changeset added at least one image" + "en": "Changeset added at least one image", + "de": "Changeset hat mindestens ein Bild hinzugefügt" } } ] @@ -641,7 +678,8 @@ { "osmTags": "theme!=grb", "question": { - "en": "Exclude GRB theme" + "en": "Exclude GRB theme", + "de": "GRB-Thema ausschließen" } } ] @@ -652,7 +690,9 @@ { "osmTags": "theme!=etymology", "question": { - "en": "Exclude etymology theme" + "en": "Exclude etymology theme", + "de": "Etymologie-Thema ausschließen", + "es": "Excluir el tema de la etimología" } } ] @@ -667,7 +707,8 @@ { "id": "link_to_more", "render": { - "en": "More statistics can be found here" + "en": "More statistics can be found here", + "de": "Weitere Statistiken findest du hier" } }, { diff --git a/assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json b/assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json index 4a55a1cf1..cde6afad7 100644 --- a/assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json +++ b/assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json @@ -1,13 +1,18 @@ { "id": "mapcomplete-changes", "title": { - "en": "Changes made with MapComplete" + "en": "Changes made with MapComplete", + "de": "Änderungen mit MapComplete" }, "shortDescription": { - "en": "Shows changes made by MapComplete" + "en": "Shows changes made by MapComplete", + "de": "Zeigt die von MapComplete vorgenommenen Änderungen an" }, "description": { - "en": "This maps shows all the changes made with MapComplete" + "en": "This maps shows all the changes made with MapComplete", + "de": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen", + "es": "Este mapa muestra todos los cambios realizados con MapComplete", + "pl": "Ta mapa pokazuje wszystkie zmiany wprowadzone za pomocą MapComplete" }, "icon": "./assets/svg/logo.svg", "hideFromOverview": true, @@ -18,7 +23,8 @@ { "id": "mapcomplete-changes", "name": { - "en": "Changeset centers" + "en": "Changeset centers", + "de": "Changeset-Zentren" }, "minzoom": 0, "source": { @@ -28,41 +34,49 @@ }, "title": { "render": { - "en": "Changeset for {theme}" + "en": "Changeset for {theme}", + "de": "Änderungssatz für {theme}" } }, "description": { - "en": "Shows all MapComplete changes" + "en": "Shows all MapComplete changes", + "de": "Zeigt alle MapComplete-Änderungen", + "es": "Muestra todos los cambios de MapComplete" }, "tagRenderings": [ { "id": "show_changeset_id", "render": { - "en": "Changeset {id}" + "en": "Changeset {id}", + "de": "Änderungssatz {id}" } }, { "id": "contributor", "question": { - "en": "What contributor did make this change?" + "en": "What contributor did make this change?", + "de": "Wer hat zu dieser Änderung beigetragen?" }, "freeform": { "key": "user" }, "render": { - "en": "Change made by {user}" + "en": "Change made by {user}", + "de": "Änderung vorgenommen von {user}" } }, { "id": "theme-id", "question": { - "en": "What theme was used to make this change?" + "en": "What theme was used to make this change?", + "de": "Welches Thema wurde für diese Änderung verwendet?" }, "freeform": { "key": "theme" }, "render": { - "en": "Change with theme {theme}" + "en": "Change with theme {theme}", + "de": "Änderung mit Thema {theme}" } }, { @@ -71,19 +85,23 @@ "key": "locale" }, "question": { - "en": "What locale (language) was this change made in?" + "en": "What locale (language) was this change made in?", + "de": "In welcher Sprache (Locale) wurde diese Änderung vorgenommen?" }, "render": { - "en": "User locale is {locale}" + "en": "User locale is {locale}", + "de": "Die Benutzersprache ist {locale}" } }, { "id": "host", "render": { - "en": "Change with with {host}" + "en": "Change with with {host}", + "de": "Änderung mit {host}" }, "question": { - "en": "What host (website) was this change made with?" + "en": "What host (website) was this change made with?", + "de": "Bei welchem Host (Website) wurde diese Änderung vorgenommen?" }, "freeform": { "key": "host" @@ -104,10 +122,12 @@ { "id": "version", "question": { - "en": "What version of MapComplete was used to make this change?" + "en": "What version of MapComplete was used to make this change?", + "de": "Welche Version von MapComplete wurde verwendet, um diese Änderung vorzunehmen?" }, "render": { - "en": "Made with {editor}" + "en": "Made with {editor}", + "de": "Erstellt mit {editor}" }, "freeform": { "key": "editor" @@ -143,7 +163,10 @@ } ], "question": { - "en": "Themename contains {search}" + "en": "Themename contains {search}", + "de": "Themenname enthält {search}", + "es": "El nombre contiene {search}", + "pl": "Nazwa tematu zawiera {search}" } } ] @@ -159,7 +182,9 @@ } ], "question": { - "en": "Themename does not contain {search}" + "en": "Themename does not contain {search}", + "de": "Themename enthält nicht {search}", + "es": "El nombre del tema no contiene {search}" } } ] @@ -175,7 +200,9 @@ } ], "question": { - "en": "Made by contributor {search}" + "en": "Made by contributor {search}", + "de": "Erstellt von Mitwirkendem {search}", + "es": "Hecho por el colaborador {search}" } } ] @@ -191,7 +218,9 @@ } ], "question": { - "en": "Not made by contributor {search}" + "en": "Not made by contributor {search}", + "de": "Nicht erstellt von Mitwirkendem {search}", + "es": "No realizado por el colaborador {search}" } } ] @@ -208,7 +237,9 @@ } ], "question": { - "en": "Made before {search}" + "en": "Made before {search}", + "de": "Erstellt vor {search}", + "es": "Realizado antes de {search}" } } ] @@ -225,7 +256,9 @@ } ], "question": { - "en": "Made after {search}" + "en": "Made after {search}", + "de": "Erstellt nach {search}", + "es": "Realizado después de {search}" } } ] @@ -241,7 +274,9 @@ } ], "question": { - "en": "User language (iso-code) {search}" + "en": "User language (iso-code) {search}", + "de": "Benutzersprache (ISO-Code) {search}", + "es": "Idioma del usuario (código iso) {search}" } } ] @@ -257,7 +292,8 @@ } ], "question": { - "en": "Made with host {search}" + "en": "Made with host {search}", + "de": "Erstellt mit Host {search}" } } ] @@ -268,7 +304,8 @@ { "osmTags": "add-image>0", "question": { - "en": "Changeset added at least one image" + "en": "Changeset added at least one image", + "de": "Changeset hat mindestens ein Bild hinzugefügt" } } ] @@ -279,7 +316,8 @@ { "osmTags": "theme!=grb", "question": { - "en": "Exclude GRB theme" + "en": "Exclude GRB theme", + "de": "GRB-Thema ausschließen" } } ] @@ -290,7 +328,9 @@ { "osmTags": "theme!=etymology", "question": { - "en": "Exclude etymology theme" + "en": "Exclude etymology theme", + "de": "Etymologie-Thema ausschließen", + "es": "Excluir el tema de la etimología" } } ] @@ -305,7 +345,8 @@ { "id": "link_to_more", "render": { - "en": "More statistics can be found here" + "en": "More statistics can be found here", + "de": "Weitere Statistiken findest du hier" } }, { diff --git a/assets/themes/surveillance/surveillance.json b/assets/themes/surveillance/surveillance.json index 684c36660..83fd347e5 100644 --- a/assets/themes/surveillance/surveillance.json +++ b/assets/themes/surveillance/surveillance.json @@ -59,7 +59,8 @@ "override": { "minzoom": 12 } - } + }, + "police" ], "enableMorePrivacy": true } diff --git a/assets/themes/uk_addresses/uk_addresses.json b/assets/themes/uk_addresses/uk_addresses.json index 85959a8e2..cecc26a2a 100644 --- a/assets/themes/uk_addresses/uk_addresses.json +++ b/assets/themes/uk_addresses/uk_addresses.json @@ -683,8 +683,8 @@ } ], "allowMove": { - "enableImproveAccuraccy": true, - "enableRelocation": false + "enableRelocation": false, + "enableImproveAccuracy": true } }, "named_streets" diff --git a/langs/de.json b/langs/de.json index 3c53df24d..3d4932ead 100644 --- a/langs/de.json +++ b/langs/de.json @@ -194,7 +194,7 @@ "josmNotOpened": "JOSM konnte nicht erreicht werden. Bitte sicherstellen, dass das Programm geöffnet und Remote Control aktiviert ist", "josmOpened": "JOSM ist geöffnet", "madeBy": "Erstellt von {author}", - "mapContributionsBy": "Die angezeigten Daten wurden bearbeitet durch {contributors}", + "mapContributionsBy": "Angezeigte Daten wurden bearbeitet durch {contributors}", "mapContributionsByAndHidden": "Die angezeigten Daten wurden bearbeitet von {contributors} und {hiddenCount} weiteren Beitragenden", "mapDataByOsm": "Kartendaten: OpenStreetMap", "mapillaryHelp": "Mapillary ist ein Online-Dienst, der Straßenbilder sammelt und sie unter einer freien Lizenz anbietet. Mitwirkende dürfen diese Bilder verwenden, um OpenStreetMap zu verbessern", diff --git a/langs/en.json b/langs/en.json index 2d71a1b48..9249b961c 100644 --- a/langs/en.json +++ b/langs/en.json @@ -633,7 +633,7 @@ "#": "These texts are shown above the theme buttons when no theme is loaded", "about": "About MapComplete", "featuredThemeTitle": "Featured this week", - "intro": "Maps about various topics which you contribute to", + "intro": "Maps about various topics which you can contribute to", "learnMore": "Learn more", "logIn": "Log in to see other themes you previously visited", "pickTheme": "Pick a theme below to get started.", @@ -865,6 +865,9 @@ "description": "a positive, whole number", "noZero": "Zero is not allowed" }, + "regex": { + "description": "a regular expression" + }, "slope": { "inputExplanation": "Place your phone on the ground with the top side of your phone pointing towards the top of the slope.", "inputIncorrect": "For correct measurements, make sure the arrow is within the green area." diff --git a/langs/es.json b/langs/es.json index a749a08a7..07f6f6e7d 100644 --- a/langs/es.json +++ b/langs/es.json @@ -420,7 +420,8 @@ "index": { "#": "Estos textos son mostrados sobre los botones del tema cuando no hay un tema cargado", "featuredThemeTitle": "Esta semana destacamos", - "intro": "Mapas sobre diversos temas a los que contribuye", + "intro": "Mapas sobre diversos temas a los que puedes contribuir", + "learnMore": "Más información", "logIn": "Inicia sesión para ver otros temas que visitaste anteriormente", "pickTheme": "Elige un tema de abajo para empezar.", "title": "MapComplete" diff --git a/langs/layers/ca.json b/langs/layers/ca.json index d68514f77..4c86e6296 100644 --- a/langs/layers/ca.json +++ b/langs/layers/ca.json @@ -5137,14 +5137,21 @@ } } }, - "11": { + "10": { + "options": { + "0": { + "question": "Editat per última vega pel contribuïdor {search}" + } + } + }, + "12": { "options": { "0": { "question": "Creada abans de {search}" } } }, - "12": { + "13": { "options": { "0": { "question": "Creada després de {search}" @@ -5178,26 +5185,19 @@ } } }, - "6": { + "7": { "options": { "0": { "question": "Obert pel contribuïdor {search}" } } }, - "7": { + "8": { "options": { "0": { "question": "No obert pel contribuïdor {search}" } } - }, - "9": { - "options": { - "0": { - "question": "Editat per última vega pel contribuïdor {search}" - } - } } }, "name": "Notes d'OpenStreetMap", diff --git a/langs/layers/cs.json b/langs/layers/cs.json index c03cc9d89..ed4248732 100644 --- a/langs/layers/cs.json +++ b/langs/layers/cs.json @@ -5363,14 +5363,21 @@ } } }, - "11": { + "10": { + "options": { + "0": { + "question": "Naposledy upravil přispěvatel {search}" + } + } + }, + "12": { "options": { "0": { "question": "Vytvořeno před {search}" } } }, - "12": { + "13": { "options": { "0": { "question": "Vytvořeno po {search}" @@ -5404,26 +5411,19 @@ } } }, - "6": { + "7": { "options": { "0": { "question": "Otevřeno přispěvatelem {search}" } } }, - "7": { + "8": { "options": { "0": { "question": "Není otevřeno přispěvatelem {search}" } } - }, - "9": { - "options": { - "0": { - "question": "Naposledy upravil přispěvatel {search}" - } - } } }, "name": "Poznámky OpenStreetMap", diff --git a/langs/layers/da.json b/langs/layers/da.json index 470168d53..e974a01e3 100644 --- a/langs/layers/da.json +++ b/langs/layers/da.json @@ -1640,7 +1640,7 @@ }, "note": { "filter": { - "9": { + "10": { "options": { "0": { "question": "Senest redigeret af bidragsyder {search}" diff --git a/langs/layers/de.json b/langs/layers/de.json index 07e378a6c..824848c0a 100644 --- a/langs/layers/de.json +++ b/langs/layers/de.json @@ -6777,14 +6777,21 @@ } } }, - "11": { + "10": { + "options": { + "0": { + "question": "Zuletzt bearbeitet von {search}" + } + } + }, + "12": { "options": { "0": { "question": "Erstellt vor dem {search}" } } }, - "12": { + "13": { "options": { "0": { "question": "Erstellt nach dem {search}" @@ -6818,26 +6825,19 @@ } } }, - "6": { + "7": { "options": { "0": { "question": "Erstellt von {search}" } } }, - "7": { + "8": { "options": { "0": { "question": "Nicht erstellt von {search}" } } - }, - "9": { - "options": { - "0": { - "question": "Zuletzt bearbeitet von {search}" - } - } } }, "name": "OpenStreetMap-Hinweise", diff --git a/langs/layers/en.json b/langs/layers/en.json index 22879c24c..d9f4ed528 100644 --- a/langs/layers/en.json +++ b/langs/layers/en.json @@ -6805,32 +6805,39 @@ "10": { "options": { "0": { - "question": "Not edited as last by {search}" + "question": "Last edited by contributor {search}" } } }, "11": { "options": { "0": { - "question": "Created before {search}" + "question": "Not edited as last by {search}" } } }, "12": { "options": { "0": { - "question": "Created after {search}" + "question": "Created before {search}" } } }, "13": { "options": { "0": { - "question": "Last edited before {search}" + "question": "Created after {search}" } } }, "14": { + "options": { + "0": { + "question": "Last edited before {search}" + } + } + }, + "15": { "options": { "0": { "question": "Last edited after {search}" @@ -6874,28 +6881,28 @@ "6": { "options": { "0": { - "question": "Opened by contributor {search}" + "question": "Should not mention {search} in any comment" } } }, "7": { "options": { "0": { - "question": "Not opened by contributor {search}" + "question": "Opened by contributor {search}" } } }, "8": { "options": { "0": { - "question": "Edited or commented on by any user with name {search}" + "question": "Not opened by contributor {search}" } } }, "9": { "options": { "0": { - "question": "Last edited by contributor {search}" + "question": "Edited or commented on by any user with name {search}" } } } @@ -7716,6 +7723,50 @@ "render": "Playground device" } }, + "police": { + "description": "Many types of police facilities ", + "name": "Police stations", + "presets": { + "0": { + "description": "A police office where the general public can enter for inquiries", + "title": "a police office" + }, + "1": { + "description": "A place where police performs checks on travelling people", + "title": "a police checkpoint" + }, + "2": { + "description": "An administrative police office without services for the general public.", + "title": "an administrative, police backoffice" + }, + "3": { + "description": "A jail run by the police without public services. People are detained here for a short time (at most a few days), e.g. for small misdemeanors, disturbance of the public order or awaiting a trial" + }, + "4": { + "description": "A naval or maritime base for the maritime police; often with a pier and police boats nearby" + } + }, + "tagRenderings": { + "4_z2nrdhy6tyyh4fd": { + "mappings": { + "0": { + "then": "This police office has some cells to detain people" + }, + "1": { + "then": "This police office does not have cells to detain people" + } + }, + "question": "Does this police office have detention facilities?" + }, + "police_name": { + "question": "What is the name of this police facility?", + "render": "{name}" + } + }, + "title": { + "render": "{name}" + } + }, "postboxes": { "description": "The layer showing postboxes.", "name": "Postboxes", diff --git a/langs/layers/es.json b/langs/layers/es.json index 11f734069..d580816d2 100644 --- a/langs/layers/es.json +++ b/langs/layers/es.json @@ -3146,14 +3146,21 @@ } } }, - "11": { + "10": { + "options": { + "0": { + "question": "Editada por última vez por el contributor {search}" + } + } + }, + "12": { "options": { "0": { "question": "Creada antes de {search}" } } }, - "12": { + "13": { "options": { "0": { "question": "Creada después de {search}" @@ -3187,26 +3194,19 @@ } } }, - "6": { + "7": { "options": { "0": { "question": "Abierto por el contributor {search}" } } }, - "7": { + "8": { "options": { "0": { "question": "No abierto por el contributor {search}" } } - }, - "9": { - "options": { - "0": { - "question": "Editada por última vez por el contributor {search}" - } - } } }, "name": "Notas de OpenStreetMap", diff --git a/langs/layers/fr.json b/langs/layers/fr.json index 5c6484521..a3e9c61b1 100644 --- a/langs/layers/fr.json +++ b/langs/layers/fr.json @@ -4439,14 +4439,21 @@ } } }, - "11": { + "10": { + "options": { + "0": { + "question": "Dernière modification par {search}" + } + } + }, + "12": { "options": { "0": { "question": "Créée avant le {search}" } } }, - "12": { + "13": { "options": { "0": { "question": "Créée après le {search}" @@ -4460,26 +4467,19 @@ } } }, - "6": { + "7": { "options": { "0": { "question": "Ouverte par {search}" } } }, - "7": { + "8": { "options": { "0": { "question": "Exclureles notes ouvertes par {search}" } } - }, - "9": { - "options": { - "0": { - "question": "Dernière modification par {search}" - } - } } }, "name": "Notes OpenStreetMap", diff --git a/langs/layers/nl.json b/langs/layers/nl.json index 5e790d218..181afe19c 100644 --- a/langs/layers/nl.json +++ b/langs/layers/nl.json @@ -5566,14 +5566,21 @@ } } }, - "11": { + "10": { + "options": { + "0": { + "question": "Laatst bewerkt door bijdrager {search}" + } + } + }, + "12": { "options": { "0": { "question": "Aangemaakt voor {search}" } } }, - "12": { + "13": { "options": { "0": { "question": "Aangemaakt na {search}" @@ -5607,26 +5614,19 @@ } } }, - "6": { + "7": { "options": { "0": { "question": "Geopend door bijdrager {search}" } } }, - "7": { + "8": { "options": { "0": { "question": "Niet geopend door bijdrager {search}" } } - }, - "9": { - "options": { - "0": { - "question": "Laatst bewerkt door bijdrager {search}" - } - } } }, "name": "OpenStreetMap Notes", diff --git a/langs/themes/es.json b/langs/themes/es.json index ef19ec679..ae9284db1 100644 --- a/langs/themes/es.json +++ b/langs/themes/es.json @@ -808,6 +808,72 @@ "description": "Los faros son edificios altos con una luz en la parte superior para guiar el tráfico marítimo.", "title": "Faros" }, + "mapcomplete-changes": { + "description": "Este mapa muestra todos los cambios realizados con MapComplete", + "layers": { + "0": { + "description": "Muestra todos los cambios de MapComplete", + "filter": { + "0": { + "options": { + "0": { + "question": "El nombre contiene {search}" + } + } + }, + "1": { + "options": { + "0": { + "question": "El nombre del tema no contiene {search}" + } + } + }, + "10": { + "options": { + "0": { + "question": "Excluir el tema de la etimología" + } + } + }, + "2": { + "options": { + "0": { + "question": "Hecho por el colaborador {search}" + } + } + }, + "3": { + "options": { + "0": { + "question": "No realizado por el colaborador {search}" + } + } + }, + "4": { + "options": { + "0": { + "question": "Realizado antes de {search}" + } + } + }, + "5": { + "options": { + "0": { + "question": "Realizado después de {search}" + } + } + }, + "6": { + "options": { + "0": { + "question": "Idioma del usuario (código iso) {search}" + } + } + } + } + } + } + }, "maproulette": { "description": "Tema que muestra las tareas de MapRoulette, permitiendo buscarlas, filtrarlas y arreglarlas.", "title": "Tareas de MapRoulette" diff --git a/langs/themes/pl.json b/langs/themes/pl.json index e3be5755f..347bf3fdd 100644 --- a/langs/themes/pl.json +++ b/langs/themes/pl.json @@ -644,6 +644,22 @@ }, "title": "Krawężniki i przejścia" }, + "mapcomplete-changes": { + "description": "Ta mapa pokazuje wszystkie zmiany wprowadzone za pomocą MapComplete", + "layers": { + "0": { + "filter": { + "0": { + "options": { + "0": { + "question": "Nazwa tematu zawiera {search}" + } + } + } + } + } + } + }, "maproulette": { "description": "Temat pokazujący zadania MapRoulette, umożliwiający ich wyszukiwanie, filtrowanie i naprawianie.", "title": "Zadania MapRoulette" diff --git a/package-lock.json b/package-lock.json index a42d04cf4..be13f6370 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mapcomplete", - "version": "0.46.8", + "version": "0.46.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mapcomplete", - "version": "0.46.8", + "version": "0.46.9", "license": "GPL-3.0-or-later", "dependencies": { "@comunica/core": "^3.0.1", diff --git a/package.json b/package.json index ec60efcbb..e8fc7ca23 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mapcomplete", - "version": "0.46.8", + "version": "0.46.9", "repository": "https://github.com/pietervdvn/MapComplete", "description": "A small website to edit OSM easily", "bugs": "https://github.com/pietervdvn/MapComplete/issues", @@ -123,7 +123,7 @@ "reuse-compliance": "reuse lint", "housekeeping": "git pull && npx update-browserslist-db@latest && npm run weblate:merge-heavy && npm run generate && npm run generate:docs && npm run generate:schemas && npm run generate:contributor-list && vite-node scripts/fetchLanguages.ts && vite-node scripts/generateSunnyUnlabeled.ts && npm run format && git add assets/ langs/ Docs/ **/*.ts Docs/* src/* && git commit -m 'chore: automated housekeeping...'", "###": "MICROSERVICES AND SERVER MAINTAINENCE", - "release": "standard-version", + "release": "standard-version && git push --follow-tags", "release:minor": "standard-version --release-as minor", "release:patch": "standard-version --release-as patch", "release:major": "standard-version --release-as major", diff --git a/scripts/ScriptUtils.ts b/scripts/ScriptUtils.ts index d006e8740..7eb369a3a 100644 --- a/scripts/ScriptUtils.ts +++ b/scripts/ScriptUtils.ts @@ -94,14 +94,28 @@ export default class ScriptUtils { }) } - public static getThemePaths(): string[] { - return ScriptUtils.readDirRecSync("./assets/themes") + public static getThemePaths(useTranslationPaths = false): string[] { + const normalFiles = ScriptUtils.readDirRecSync("./assets/themes") .filter((path) => path.endsWith(".json") && !path.endsWith(".proto.json")) .filter((path) => path.indexOf("license_info.json") < 0) + + if (!useTranslationPaths) { + return normalFiles + } + const specialfiles = ["./assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json"] + const blacklist = ["assets/themes/mapcomplete-changes/mapcomplete-changes.json"] + + const filtered = normalFiles.filter(path => !blacklist.some(black => path.endsWith(black))) + return filtered.concat(specialfiles) + } - public static getThemeFiles(): { parsed: LayoutConfigJson; path: string; raw: string }[] { - return this.getThemePaths().map((path) => { + public static getThemeFiles(useTranslationPaths = false): { + parsed: LayoutConfigJson; + path: string; + raw: string + }[] { + return this.getThemePaths(useTranslationPaths).map((path) => { try { const contents = readFileSync(path, { encoding: "utf8" }) if (contents === "") { @@ -148,6 +162,7 @@ export default class ScriptUtils { const data = await ScriptUtils.Download(url, headers) return JSON.parse(data["content"]) } + public static async DownloadFetch( url: string, headers?: any @@ -158,6 +173,7 @@ export default class ScriptUtils { console.log("Fetched", url, data) return { content: data } } + public static Download( url: string, headers?: any @@ -193,17 +209,17 @@ export default class ScriptUtils { path: urlObj.pathname + urlObj.search, port: urlObj.port, - headers: headers, + headers: headers }, (res) => { const parts: string[] = [] res.setEncoding("utf8") - res.on("data", function (chunk) { + res.on("data", function(chunk) { // @ts-ignore parts.push(chunk) }) - res.addListener("end", function () { + res.addListener("end", function() { if (res.statusCode === 301 || res.statusCode === 302) { console.log("Got a redirect:", res.headers.location) resolve({ redirect: res.headers.location }) @@ -221,7 +237,7 @@ export default class ScriptUtils { }) } ) - request.on("error", function (e) { + request.on("error", function(e) { reject(e) }) } catch (e) { diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index 1de859c67..fdc973b46 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -504,7 +504,8 @@ class LayerOverviewUtils extends Script { priviliged.delete("last_click") priviliged.delete("search") - if (priviliged.size > 0 && !forceReload) { + const isBoostrapping = AllSharedLayers.getSharedLayersConfigs().size == 0 + if (!isBoostrapping && priviliged.size > 0) { throw ( "Priviliged layer " + Array.from(priviliged).join(", ") + diff --git a/scripts/generateTranslations.ts b/scripts/generateTranslations.ts index 8521188c9..0bde6e9ee 100644 --- a/scripts/generateTranslations.ts +++ b/scripts/generateTranslations.ts @@ -670,7 +670,7 @@ function removeNonEnglishTranslations(object: any) { * Load the translations into the theme files */ function mergeThemeTranslations(englishOnly: boolean = false) { - const themeFiles = ScriptUtils.getThemeFiles() + const themeFiles = ScriptUtils.getThemeFiles(true) for (const themeFile of themeFiles) { let config = themeFile.parsed mergeLayerTranslation(config, themeFile.path, loadTranslationFilesFrom("themes")) @@ -723,7 +723,7 @@ class GenerateTranslations extends Script { { const l1 = generateTranslationsObjectFrom(ScriptUtils.getLayerFiles(), "layers") const l2 = generateTranslationsObjectFrom( - ScriptUtils.getThemeFiles().filter( + ScriptUtils.getThemeFiles(true).filter( (th) => th.parsed.mustHaveLanguage === undefined ), "themes" diff --git a/src/Logic/Web/PlantNet.ts b/src/Logic/Web/PlantNet.ts index 4012040e0..769fb60c9 100644 --- a/src/Logic/Web/PlantNet.ts +++ b/src/Logic/Web/PlantNet.ts @@ -15,7 +15,7 @@ export default class PlantNet { for (const image of imageUrls) { url += "&images=" + encodeURIComponent(image) } - return Utils.downloadJsonCached(url, 365 * 24 * 60 * 60 * 1000) + return Utils.downloadJsonCached(url, 365 * 24 * 60 * 60 * 1000, undefined, true) } public static exampleResult: PlantNetResult = { diff --git a/src/Models/Constants.ts b/src/Models/Constants.ts index c10cdd438..fc3061632 100644 --- a/src/Models/Constants.ts +++ b/src/Models/Constants.ts @@ -86,17 +86,29 @@ export default class Constants { static distanceToChangeObjectBins = [25, 50, 100, 500, 1000, 5000, Number.MAX_VALUE] static themeOrder = [ "personal", + "cyclofix", - "waste", "etymology", + "waste", + "food", "cafes_and_pubs", "shops", - "playgrounds", - "hailhydrant", - "toilets", - "aed", + "healthcare", + "sports", + + "artwork", "bookcases", + "playgrounds", + "drinking_water", + "toilets", + "vending_machine", + "aed", + "clock", + + "surveillance", + "advertising", + "circular_economy", ] /** * Upon initialization, the GPS will search the location. diff --git a/src/Models/FilteredLayer.ts b/src/Models/FilteredLayer.ts index 2ced53af5..01b5de0b8 100644 --- a/src/Models/FilteredLayer.ts +++ b/src/Models/FilteredLayer.ts @@ -131,6 +131,13 @@ export default class FilteredLayer { return values } + /** + * import Translations from "../UI/i18n/Translations" + * import { RegexTag } from "../Logic/Tags/RegexTag" + * + * const option: FilterConfigOption = {question: Translations.T("question"), osmTags: undefined, originalTagsSpec: "key~.*{search}.*", fields: [{name: "search", type: "string"}] } + * FilteredLayer.fieldsToTags(option, {search: "value_regex"}) // => new RegexTag("key", /^(.*(value_regex).*)$/) + */ private static fieldsToTags( option: FilterConfigOption, fieldstate: string | Record @@ -153,7 +160,7 @@ export default class FilteredLayer { } for (const key in properties) { - v = (v).replace("{" + key + "}", properties[key]) + v = (v).replace("{" + key + "}", "(" + properties[key] + ")") } return v diff --git a/src/Models/ThemeConfig/FilterConfig.ts b/src/Models/ThemeConfig/FilterConfig.ts index c2fcae675..73eea0297 100644 --- a/src/Models/ThemeConfig/FilterConfig.ts +++ b/src/Models/ThemeConfig/FilterConfig.ts @@ -60,7 +60,7 @@ export default class FilterConfig { } const fields: { name: string; type: ValidatorType }[] = (option.fields ?? []).map((f, i) => { - const type = f.type ?? "string" + const type = f.type ?? "regex" if(Validators.availableTypes.indexOf(type) < 0){ throw `Invalid filter: type is not a valid validator. Did you mean one of ${Utils.sortedByLevenshteinDistance(type, Validators.availableTypes, x => x).slice(0, 3)}` } @@ -70,12 +70,12 @@ export default class FilterConfig { } return { name: f.name, - type, + type } }) for (const field of fields) { - for (let ln in question.translations) { + for (const ln in question.translations) { const txt = question.translations[ln] if (ln.startsWith("_")) { continue @@ -226,7 +226,7 @@ export default class FilterConfig { opt.osmTags?.asHumanString() ?? "", opt.fields?.length > 0 ? opt.fields.map((f) => f.name + " (" + f.type + ")").join(" ") - : undefined, + : undefined ]) ) }) diff --git a/src/UI/BigComponents/FilterviewWithFields.svelte b/src/UI/BigComponents/FilterviewWithFields.svelte index 9d9a52e43..5245c9c2f 100644 --- a/src/UI/BigComponents/FilterviewWithFields.svelte +++ b/src/UI/BigComponents/FilterviewWithFields.svelte @@ -8,6 +8,8 @@ import { Utils } from "../../Utils" import type { ValidatorType } from "../InputElement/Validators" import InputHelper from "../InputElement/InputHelper.svelte" + import { Translation } from "../i18n/Translation" + import Tr from "../Base/Tr.svelte" export let filteredLayer: FilteredLayer export let option: FilterConfigOption @@ -36,7 +38,7 @@ appliedFilter?.setData(FilteredLayer.fieldsToString(properties)) } - let firstValue : UIEventSource + let firstValue: UIEventSource for (const field of option.fields) { // A bit of cheating: the 'parts' will have '}' suffixed for fields const src = new UIEventSource(initialState[field.name] ?? "") @@ -47,9 +49,10 @@ onDestroy( src.stabilized(200).addCallback(() => { setFields() - }), + }) ) } + let feedback: UIEventSource = new UIEventSource(undefined)
0}> @@ -58,11 +61,15 @@ - + {:else} {@html part["message"]} {/if} {/each} + {#if $feedback} + + {/if}
diff --git a/src/UI/BigComponents/MenuDrawer.svelte b/src/UI/BigComponents/MenuDrawer.svelte index d5bad56e2..c8fd4ba93 100644 --- a/src/UI/BigComponents/MenuDrawer.svelte +++ b/src/UI/BigComponents/MenuDrawer.svelte @@ -90,13 +90,13 @@
{#if $userdetails.img} - + avatar {/if} {$userdetails.name}
- + diff --git a/src/UI/InputElement/Helpers/OpeningHours/OHTable.svelte b/src/UI/InputElement/Helpers/OpeningHours/OHTable.svelte index a95f1d383..9d845dafe 100644 --- a/src/UI/InputElement/Helpers/OpeningHours/OHTable.svelte +++ b/src/UI/InputElement/Helpers/OpeningHours/OHTable.svelte @@ -220,8 +220,8 @@ {/if} {#each range(7) as wd} - startSelection(wd, h)} on:end={() => endSelection(wd, h)} - on:move={() => moved(wd, h)} on:clear={() => clearSelection()} /> + startSelection(wd, h + 0.5)} on:end={() => endSelection(wd, h + 0.5)} + on:move={() => moved(wd, h + 0.5)} on:clear={() => clearSelection()} /> {/each} diff --git a/src/UI/InputElement/Validators.ts b/src/UI/InputElement/Validators.ts index ec0896948..eb768f2b1 100644 --- a/src/UI/InputElement/Validators.ts +++ b/src/UI/InputElement/Validators.ts @@ -15,9 +15,6 @@ import UrlValidator from "./Validators/UrlValidator" import PhoneValidator from "./Validators/PhoneValidator" import OpeningHoursValidator from "./Validators/OpeningHoursValidator" import ColorValidator from "./Validators/ColorValidator" -import BaseUIElement from "../BaseUIElement" -import Combine from "../Base/Combine" -import Title from "../Base/Title" import SimpleTagValidator from "./Validators/SimpleTagValidator" import ImageUrlValidator from "./Validators/ImageUrlValidator" import TagKeyValidator from "./Validators/TagKeyValidator" @@ -30,6 +27,7 @@ import SlopeValidator from "./Validators/SlopeValidator" import VeloparkValidator from "./Validators/VeloparkValidator" import NameSuggestionIndexValidator from "./Validators/NameSuggestionIndexValidator" import CurrencyValidator from "./Validators/CurrencyValidator" +import RegexValidator from "./Validators/RegexValidator" export type ValidatorType = (typeof Validators.availableTypes)[number] @@ -64,6 +62,7 @@ export default class Validators { "velopark", "nsi", "currency", + "regex" ] as const public static readonly AllValidators: ReadonlyArray = [ @@ -95,6 +94,7 @@ export default class Validators { new VeloparkValidator(), new NameSuggestionIndexValidator(), new CurrencyValidator(), + new RegexValidator() ] private static _byType = Validators._byTypeConstructor() diff --git a/src/UI/InputElement/Validators/RegexValidator.ts b/src/UI/InputElement/Validators/RegexValidator.ts new file mode 100644 index 000000000..9323db8fd --- /dev/null +++ b/src/UI/InputElement/Validators/RegexValidator.ts @@ -0,0 +1,22 @@ +import StringValidator from "./StringValidator" +import { s } from "vitest/dist/env-afee91f0" +import { Translation } from "../../i18n/Translation" +import Translations from "../../i18n/Translations" + +export default class RegexValidator extends StringValidator{ + constructor() { + super("regex", "Validates a regex") + } + + getFeedback(s: string): Translation | undefined { + try{ + new RegExp(s) + }catch (e) { + return Translations.T("Not a valid Regex: "+e) + } + } + + isValid(s: string): boolean { + return this.getFeedback(s) === undefined + } +} diff --git a/src/UI/PlantNet/PlantNet.svelte b/src/UI/PlantNet/PlantNet.svelte index 893aa86c1..d9f0651cd 100644 --- a/src/UI/PlantNet/PlantNet.svelte +++ b/src/UI/PlantNet/PlantNet.svelte @@ -9,8 +9,8 @@ import BackButton from "../Base/BackButton.svelte" import NextButton from "../Base/NextButton.svelte" import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte" - import { createEventDispatcher } from "svelte" import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte" + import ArrowPath from "@babeard/svelte-heroicons/mini/ArrowPath" /** * The main entry point for the plantnet wizard @@ -23,7 +23,6 @@ */ export let imageUrls: Store export let onConfirm: (wikidataId: string) => void - const dispatch = createEventDispatcher<{ selected: string }>() let collapsedMode = true let options: UIEventSource = new UIEventSource( undefined @@ -38,18 +37,20 @@ let done = false - function speciesSelected(species: PlantNetSpeciesMatch) { + function speciesSelected(species: string) { console.log("Selected:", species) selectedOption = species } async function detectSpecies() { + error = undefined collapsedMode = false try { const result = await PlantNet.query(imageUrls.data.slice(0, 5)) options.set(result.results.filter((r) => r.score > 0.005).slice(0, 8)) } catch (e) { + console.error("Caught", e) error = e } } @@ -60,8 +61,12 @@ - {:else if $error !== undefined} + {:else if error !== undefined} + {:else if $imageUrls.length === 0}
diff --git a/src/UI/Popup/AllTagsPanel.svelte b/src/UI/Popup/AllTagsPanel.svelte index 519b06189..1808a64e8 100644 --- a/src/UI/Popup/AllTagsPanel.svelte +++ b/src/UI/Popup/AllTagsPanel.svelte @@ -4,6 +4,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import Searchbar from "../Base/Searchbar.svelte" import Translations from "../i18n/Translations" + import { Utils } from "../../Utils" export let tags: UIEventSource> export let tagKeys = tags.map((tgs) => (tgs === undefined ? [] : Object.keys(tgs))) @@ -34,10 +35,19 @@ const metaKeys: string[] = [].concat(...SimpleMetaTaggers.metatags.map((k) => k.keys)) let allCalculatedTags = new Set([...calculatedTags, ...metaKeys]) let search = new UIEventSource("") + + function downloadAsJson(){ + Utils.offerContentsAsDownloadableFile( + JSON.stringify(tags.data, null, " "), "tags-"+(tags.data.id ?? layer?.id ?? "")+".json" + ) + }
+ diff --git a/src/UI/Studio/CollapsedTagRenderingPreview.svelte b/src/UI/Studio/CollapsedTagRenderingPreview.svelte index 9c21d82ae..2552f6699 100644 --- a/src/UI/Studio/CollapsedTagRenderingPreview.svelte +++ b/src/UI/Studio/CollapsedTagRenderingPreview.svelte @@ -30,7 +30,7 @@ .getSchemaStartingWith(schema.path) .filter((part) => part.path.length - 1 === schema.path.length) - let usesOverride = value["builtin"] !== undefined + let usesOverride = value?.["builtin"] !== undefined function schemaForMultitype() { const sch = { ...schema } @@ -138,7 +138,7 @@ {:else if typeof value === "string"} Builtin: {value} - {:else if value["builtin"]} + {:else if value?.["builtin"]} reused tagrendering {JSON.stringify(value["builtin"])} {:else} diff --git a/src/UI/Studio/EditLayerState.ts b/src/UI/Studio/EditLayerState.ts index 3fb627a4e..871b75f17 100644 --- a/src/UI/Studio/EditLayerState.ts +++ b/src/UI/Studio/EditLayerState.ts @@ -159,6 +159,9 @@ export abstract class EditJsonState { } public getSchemaStartingWith(path: string[]) { + if(path === undefined){ + return undefined + } return this.schema.filter( (sch) => !path.some((part, i) => !(sch.path.length > path.length && sch.path[i] === part)) diff --git a/src/UI/Studio/SchemaBasedArray.svelte b/src/UI/Studio/SchemaBasedArray.svelte index 21bd1259f..ca874a262 100644 --- a/src/UI/Studio/SchemaBasedArray.svelte +++ b/src/UI/Studio/SchemaBasedArray.svelte @@ -5,18 +5,23 @@ import { TrashIcon } from "@babeard/svelte-heroicons/mini" import ShowConversionMessage from "./ShowConversionMessage.svelte" import Markdown from "../Base/Markdown.svelte" - import type { QuestionableTagRenderingConfigJson } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" + import type { + QuestionableTagRenderingConfigJson + } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" import CollapsedTagRenderingPreview from "./CollapsedTagRenderingPreview.svelte" import { Accordion } from "flowbite-svelte" + import { Utils } from "../../Utils" export let state: EditJsonState export let path: (string | number)[] = [] let schema: ConfigMeta = state.getSchema(path)[0] + console.log("SBA got schema", schema, "for path", path) - let title = schema.path.at(-1) + + let title = schema?.path?.at(-1) let singular = title if (title?.endsWith("s")) { - singular = title.slice(0, title.length - 1) + singular = title?.slice(0, title.length - 1) } let article = "a" if (singular?.match(/^[aeoui]/)) { @@ -25,18 +30,20 @@ const isTagRenderingBlock = path.length === 1 && path[0] === "tagRenderings" - if (isTagRenderingBlock) { + if (isTagRenderingBlock && schema !== undefined) { schema = { ...schema } schema.description = undefined } const subparts: ConfigMeta[] = state - .getSchemaStartingWith(schema.path) - .filter((part) => part.path.length - 1 === schema.path.length) + .getSchemaStartingWith(schema?.path) + ?.filter((part) => part.path.length - 1 === schema?.path?.length) let messages = state.messagesFor(path) let datapath = path const currentValue = state.getStoreFor<(string | QuestionableTagRenderingConfigJson)[]>(datapath) + currentValue.set(Utils.DedupT(currentValue.data)) + console.log("Current value is", currentValue.data) if (currentValue.data === undefined) { currentValue.setData([]) } @@ -62,68 +69,69 @@ currentValue.ping() } +{#if schema !== undefined} +
+

{schema.path.at(-1)}

-
-

{schema.path.at(-1)}

- - {#if subparts.length > 0} - - {/if} - {#if $currentValue === undefined} - No array defined - {:else if !Array.isArray($currentValue)} - Not an array: {typeof $currentValue} - {JSON.stringify(path)} - {JSON.stringify($currentValue).slice(0, 120)} - {:else if $currentValue?.length === 0} - No values are defined - {#if $messages.length > 0} - {#each $messages as message} - - {/each} + {#if subparts.length > 0} + {/if} - {:else if subparts.length === 0} - - {#each $currentValue as value, i} -
- - -
- {/each} - {:else} - - {#each $currentValue as value, i (value)} - + > + + +
{/each} - - {/if} -
- - {#if path.length === 1 && path[0] === "tagRenderings"} - + {#if path.length === 1 && path[0] === "tagRenderings"} + - {/if} - + > + Add a builtin tagRendering + + {/if} + +
- +{/if} diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index ce793dafe..034316fb5 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -48,7 +48,7 @@ import ChevronRight from "@babeard/svelte-heroicons/mini/ChevronRight" import ChevronLeft from "@babeard/svelte-heroicons/solid/ChevronLeft" import { Drawer } from "flowbite-svelte" - import { linear, sineIn } from "svelte/easing" + import { linear } from "svelte/easing" export let state: ThemeViewState @@ -440,7 +440,6 @@ - {#if $selectedElement !== undefined && $selectedLayer !== undefined && !$selectedLayer.popupInFloatover} @@ -494,4 +493,6 @@ {/if} {/if} + + diff --git a/src/Utils.ts b/src/Utils.ts index 8789d09a9..0dafe0de6 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -401,6 +401,19 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be return newArr } + public static DedupT(arr: T[]): T[]{ + if(!arr){ + return arr + } + const items = [] + for (const item of arr) { + if(items.indexOf(item) < 0){ + items.push(item) + } + } + return items + } + /** * Finds all duplicates in a list of strings * @@ -1064,19 +1077,22 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be public static async downloadJsonCached( url: string, maxCacheTimeMs: number, - headers?: Record + headers?: Record, + dontCacheErrors: boolean = false ): Promise { - const result = await Utils.downloadJsonCachedAdvanced(url, maxCacheTimeMs, headers) + const result = await Utils.downloadJsonCachedAdvanced(url, maxCacheTimeMs, headers, dontCacheErrors) if (result["content"]) { return result["content"] } throw result["error"] + } public static async downloadJsonCachedAdvanced( url: string, maxCacheTimeMs: number, - headers?: Record + headers?: Record, + dontCacheErrors = false ): Promise<{ content: T } | { error: string; url: string; statuscode?: number }> { const cached = Utils._download_cache.get(url) if (cached !== undefined) { @@ -1090,7 +1106,15 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be headers ) Utils._download_cache.set(url, { promise, timestamp: new Date().getTime() }) + try { + return await promise + }catch (e) { + if(dontCacheErrors){ + Utils._download_cache.delete(url) + } + throw e + } } public static async downloadJson(
Key