diff --git a/assets/icon-background.png.license b/assets/icon-background.png.license
new file mode 100644
index 0000000000..dce0f0a5f8
--- /dev/null
+++ b/assets/icon-background.png.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: Pieter Vander Vennet; OSM
+SPDX-License-Identifier: LicenseRef-LOGO AND CC-BY-SA-4.0
\ No newline at end of file
diff --git a/assets/icon-foreground.png.license b/assets/icon-foreground.png.license
new file mode 100644
index 0000000000..dce0f0a5f8
--- /dev/null
+++ b/assets/icon-foreground.png.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: Pieter Vander Vennet; OSM
+SPDX-License-Identifier: LicenseRef-LOGO AND CC-BY-SA-4.0
\ No newline at end of file
diff --git a/assets/icon-only.png.license b/assets/icon-only.png.license
new file mode 100644
index 0000000000..dce0f0a5f8
--- /dev/null
+++ b/assets/icon-only.png.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: Pieter Vander Vennet; OSM
+SPDX-License-Identifier: LicenseRef-LOGO AND CC-BY-SA-4.0
\ No newline at end of file
diff --git a/assets/layers/building/building.json b/assets/layers/building/building.json
new file mode 100644
index 0000000000..20ecc6a22b
--- /dev/null
+++ b/assets/layers/building/building.json
@@ -0,0 +1,346 @@
+{
+ "id": "building",
+ "isCounted": false,
+ "source": {
+ "osmTags": "building~*"
+ },
+ "description": {
+ "en": "All buildings"
+ },
+ "pointRendering": [
+ {
+ "location": [
+ "point"
+ ],
+ "marker": [
+ {
+ "icon": "circle",
+ "color": "white"
+ }
+ ],
+ "iconSize": "10,10"
+ }
+ ],
+ "lineRendering": [
+ {
+ "color": "#ff2222",
+ "width": 1
+ }
+ ],
+ "name": {
+ "en": "Buildings"
+ },
+ "title": {
+ "render": {
+ "en": "Building"
+ }
+ },
+ "tagRenderings": [
+ {
+ "id": "architecture",
+ "question": {
+ "en": "What is the architectural style of this building?"
+ },
+ "mappings": [
+ {
+ "if": "building:architecture=islamic",
+ "then": {
+ "en": "Islamic architecture",
+ "fr": "Architecture islamique",
+ "nl": "Islamitische architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=mamluk",
+ "then": {
+ "en": "Mamluk architecture",
+ "fr": "Architecture mamelouke",
+ "nl": "Mamelukse architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=romanesque",
+ "then": {
+ "en": "Romanesque architecture",
+ "fr": "Architecture romane",
+ "nl": "Romaanse architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=gothic",
+ "then": {
+ "en": "Gothic architecture",
+ "fr": "Architecture gothique",
+ "nl": "Gotische architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=renaissance",
+ "then": {
+ "en": "Renaissance architecture",
+ "fr": "Architecture Renaissance",
+ "nl": "Renaissance-architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=mannerism",
+ "then": {
+ "en": "Mannerism",
+ "fr": "Maniérisme",
+ "nl": "Maniërisme"
+ }
+ },
+ {
+ "if": "building:architecture=ottoman",
+ "then": {
+ "en": "Ottoman architecture",
+ "fr": "Architecture ottomane",
+ "nl": "Ottomaanse architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=baroque",
+ "then": {
+ "en": "Baroque architecture",
+ "fr": "Architecture baroque",
+ "nl": "Barokarchitectuur"
+ }
+ },
+ {
+ "if": "building:architecture=rococo",
+ "then": {
+ "en": "Rococo",
+ "fr": "Rococo",
+ "nl": "Rococo"
+ }
+ },
+ {
+ "if": "building:architecture=empire",
+ "then": {
+ "en": "Empire style",
+ "fr": "Style Empire",
+ "nl": "Empirestijl"
+ }
+ },
+ {
+ "if": "building:architecture=moorish revival",
+ "then": {
+ "en": "Moorish Revival",
+ "fr": "Architecture néo-mauresque",
+ "nl": "Neo-Moorse architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=neoclassicism",
+ "then": {
+ "en": "Neoclassical architecture",
+ "fr": "Architecture néoclassique",
+ "nl": "Neoclassicistische architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=georgian",
+ "then": {
+ "en": "Georgian architecture",
+ "fr": "Architecture géorgienne",
+ "nl": "Georgian architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=victorian",
+ "then": {
+ "en": "Victorian architecture",
+ "fr": "Architecture victorienne",
+ "nl": "Victoriaanse architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=historicism",
+ "then": {
+ "en": "Historicism",
+ "fr": "Historicisme",
+ "nl": "Historisme"
+ }
+ },
+ {
+ "if": "building:architecture=neo-romanesque",
+ "then": {
+ "en": "Romanesque Revival",
+ "fr": "Architecture néo-romane",
+ "nl": "Neo-Romaanse architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=neo-byzantine",
+ "then": {
+ "en": "Byzantine Revival",
+ "fr": "Architecture néo-byzantine",
+ "nl": "Neo-Byzantijnse architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=neo-gothic",
+ "then": {
+ "en": "Gothic Revival",
+ "fr": "Architecture néo-gothique",
+ "nl": "Neo-Gotische architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=neo-renaissance",
+ "then": {
+ "en": "Renaissance Revival",
+ "fr": "Architecture néo-Renaissance",
+ "nl": "Neo-Renaissance architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=neo-baroque",
+ "then": {
+ "en": "Baroque Revival",
+ "fr": "Architecture néo-baroque",
+ "nl": "Neo-Barokarchitectuur"
+ }
+ },
+ {
+ "if": "building:architecture=art_nouveau",
+ "then": {
+ "en": "Art Nouveau",
+ "fr": "Art nouveau",
+ "nl": "Art Nouveau"
+ }
+ },
+ {
+ "if": "building:architecture=eclectic",
+ "then": {
+ "en": "Eclecticism in architecture",
+ "fr": "Éclectisme en architecture",
+ "nl": "Eclecticisme in architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=functionalism",
+ "then": {
+ "en": "Functionalism",
+ "fr": "Fonctionnalisme",
+ "nl": "Functionalisme"
+ }
+ },
+ {
+ "if": "building:architecture=cubism",
+ "then": {
+ "en": "Cubism",
+ "fr": "Cubisme",
+ "nl": "Kubisme"
+ }
+ },
+ {
+ "if": "building:architecture=new_objectivity",
+ "then": {
+ "en": "New Objectivity",
+ "fr": "Nouvelle Objectivité",
+ "nl": "Nieuwe Zakelijkheid"
+ }
+ },
+ {
+ "if": "building:architecture=art_deco",
+ "then": {
+ "en": "Art Deco",
+ "fr": "Art déco",
+ "nl": "Art Deco"
+ }
+ },
+ {
+ "if": "building:architecture=modern",
+ "then": {
+ "en": "Modern architecture",
+ "fr": "Architecture moderne",
+ "nl": "Moderne architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=amsterdam_school",
+ "then": {
+ "en": "Amsterdam School",
+ "fr": "École d'Amsterdam",
+ "nl": "Amsterdamse School"
+ }
+ },
+ {
+ "if": "building:architecture=international_style",
+ "then": {
+ "en": "International Style",
+ "fr": "Style international",
+ "nl": "Internationale Stijl"
+ }
+ },
+ {
+ "if": "building:architecture=constructivism",
+ "then": {
+ "en": "Constructivism",
+ "fr": "Constructivisme",
+ "nl": "Constructivisme"
+ }
+ },
+ {
+ "if": "building:architecture=stalinist_neoclassicism",
+ "then": {
+ "en": "Stalinist architecture",
+ "fr": "Architecture stalinienne",
+ "nl": "Stalinistische architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=brutalist",
+ "then": {
+ "en": "Brutalist architecture",
+ "fr": "Architecture brutaliste",
+ "nl": "Brutalistische architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=postmodern",
+ "then": {
+ "en": "Postmodern architecture",
+ "fr": "Architecture postmoderne",
+ "nl": "Postmoderne architectuur"
+ }
+ },
+ {
+ "if": "building:architecture=contemporary",
+ "then": {
+ "en": "Contemporary architecture",
+ "fr": "Architecture contemporaine",
+ "nl": "Hedendaagse architectuur"
+ }
+ }
+ ],
+ "render": {
+ "en": "{building:architecture}"
+ },
+ "multiAnswer": true,
+ "freeform": {
+ "key": "building:architecture"
+ }
+ },
+ {
+ "id": "construction_date",
+ "question": {
+ "en": "When was this built?"
+ },
+ "render": {
+ "en": "Built in {construction_date}"
+ },
+ "freeform": {
+ "key": "construction_date",
+ "type": "date"
+ }
+ },
+ "address.address"
+ ],
+ "minzoom": 18,
+ "allowMove": {
+ "enableRelocation": false,
+ "enableImproveAccuracy": true
+ }
+}
diff --git a/assets/layers/childcare/kindergarten.svg.license b/assets/layers/childcare/kindergarten.svg.license
deleted file mode 100644
index 5f03c70c71..0000000000
--- a/assets/layers/childcare/kindergarten.svg.license
+++ /dev/null
@@ -1,2 +0,0 @@
-SPDX-FileCopyrightText: Diego Naive; VideoPlasty; Pietervdvn
-SPDX-License-Identifier: CC-BY-4.0
\ No newline at end of file
diff --git a/assets/layers/climbing/climbing.json b/assets/layers/climbing/climbing.json
index 0bbedac561..d5580174e5 100644
--- a/assets/layers/climbing/climbing.json
+++ b/assets/layers/climbing/climbing.json
@@ -83,7 +83,7 @@
"it": "Qual è il livello della via più facile qua, secondo il sistema di classificazione francese?",
"cs": "Jaký je stupeň nejjednodušší trasy podle francouzského klasifikačního systému?",
"es": "¿Cuál es el grado de la vía más fácil aquí, según el sistema de clasificación francés?",
- "ca": "Quin és el grau de la ruta més fàcil aquí, segons el sistema de classificació francès?"
+ "ca": "Quin és el grau de la ruta més fàcil aquí segons el sistema de classificació francès?"
},
"render": {
"de": "Die leichteste Route hat hier die Schwierigkeit {climbing:grade:french:min} (französisch/belgisches System)",
@@ -94,7 +94,7 @@
"it": "Il minimo livello di difficoltà è {climbing:grade:french:min} secondo il sistema francese/belga",
"cs": "Nejnižší stupeň je {climbing:grade:french:min} podle francouzského/belgického systému",
"es": "El grado más bajo es {climbing:grade:french:min} según el sistema francés/belga",
- "ca": "La nota més baixa és {climbing:grade:french:min} segons el sistema francès/belga"
+ "ca": "El grau més baix és {climbing:grade:french:min} segons el sistema francès/belga"
},
"freeform": {
"key": "climbing:grade:french:min"
@@ -111,7 +111,7 @@
"it": "Qual è il livello della via più difficile qua, secondo il sistema di classificazione francese?",
"cs": "Jaká je zde trasa nejvyššího stupně podle francouzského klasifikačního systému?",
"es": "¿Cuál es la vía de mayor grado aquí, según el sistema de clasificación francés?",
- "ca": "Quina és la ruta de grau més alt d'aquí, segons el sistema de classificació francès?"
+ "ca": "Quina és la ruta de major aquí, segons el sistema de classificació francès?"
},
"render": {
"de": "Die schwierigste Route hat hier die Schwierigkeitsstufe {climbing:grade:french:max} (französisch/belgisches System)",
@@ -122,7 +122,7 @@
"it": "Il massimo livello di difficoltà è {climbing:grade:french:max} secondo il sistema francese/belga",
"cs": "Nejvyšší stupeň je {climbing:grade:french:max} podle francouzského/belgického systému",
"es": "El grado más alto es {climbing:grade:french:max} según el sistema francés/belga",
- "ca": "La nota més alta és {climbing:grade:french:max} segons el sistema francès/belga"
+ "ca": "La grau més alt és {climbing:grade:french:max} segons el sistema francès/belga"
},
"freeform": {
"key": "climbing:grade:french:max"
@@ -228,7 +228,7 @@
"it": "È possibile arrampicarsi con la corda dall’alto qua?",
"cs": "Je zde možné lezení po laně?",
"es": "¿Es posible la escalada con cuerda desde arriba aquí?",
- "ca": "És possible l'escalada propícia aquí?"
+ "ca": "És possible l'escalada en politja aquí?"
},
"mappings": [
{
@@ -242,7 +242,7 @@
"it": "È possibile arrampicarsi con moulinette qua",
"cs": "Lezení po laně je zde možné",
"es": "La escalada con cuerda desde arriba es posible aquí",
- "ca": "L'escalada propícia és possible aquí"
+ "ca": "L'escalada en politja és possible aquí"
}
},
{
@@ -256,7 +256,7 @@
"it": "Non è possibile arrampicarsi con moulinette qua",
"cs": "Lezení po laně zde není možné",
"es": "La escalada con cuerda desde arriba no es posible aquí",
- "ca": "L'escalada propícia no és possible aquí"
+ "ca": "L'escalada en politja no és possible aquí"
}
},
{
@@ -270,7 +270,7 @@
"it": "Sono presenti {climbing:toprope} vie con moulinette",
"cs": "Je zde {climbing:toprope} tras pro lezení na laně",
"es": "Hay {climbing:toprope} vías de escalada con cuerda desde arriba",
- "ca": "Hi ha {climbing:toprope} rutes específiques"
+ "ca": "Hi ha {climbing:toprope} rutes d'escalada en politja"
},
"hideInAnswer": true
}
@@ -357,7 +357,7 @@
"it": "usando attrezzi propri, ad es. dadi",
"cs": "Pomocí vlastního zařízení, např. klíny",
"es": "Usando tu propio equipo, p. ej., fisureros",
- "ca": "Utilitzant el vostre propi engranatge, p. ex., chocks"
+ "ca": "Utilitzant el vostre propi equipament, p. ex., cales"
},
"mappings": [
{
@@ -396,7 +396,7 @@
"it": "Sono presenti {climbing:traditional} vie di arrampicata tradizionale",
"cs": "Existují {climbing:traditional} tradiční lezecké cesty",
"es": "Hay {climbing:traditional} vías de escalada tradicional",
- "ca": "Hi ha {climbing:traditional} vies d'escalada tradicionals"
+ "ca": "Hi ha {climbing:traditional} rutes d'escalada tradicionals"
},
"hideInAnswer": true
}
@@ -410,7 +410,7 @@
"nl": "Wat is het maximum aantal bouten in routes ban {title()}?",
"cs": "Kolik šroubů na trasu {title()} je potřeba?",
"es": "¿Cuántos parabolts tienen como máximo las vías en {title()}?",
- "ca": "Quants parabolts tenen com a màxim les rutes a {title()} ?"
+ "ca": "Quants ancoratges d'anella tenen com a màxim les rutes a {title()} ?"
},
"render": {
"en": "The sport climbing routes here have at most {climbing:bolts:max} bolts.
This is without belay stations and indicates how much quickdraws a climber needs.
",
diff --git a/assets/layers/climbing_area/climbing_area.json b/assets/layers/climbing_area/climbing_area.json
index 160355b59f..f9cb91e6f8 100644
--- a/assets/layers/climbing_area/climbing_area.json
+++ b/assets/layers/climbing_area/climbing_area.json
@@ -70,7 +70,7 @@
"nl": "Klimrots of klimzone {name}",
"cs": "Lezecká cesta {name}",
"es": "Pared de escalada {name}",
- "ca": "Trenca d'escalada {name}"
+ "ca": "Paret d'escalada {name}"
}
},
{
@@ -310,7 +310,7 @@
"nl": "Een klimzone - een enkele rots of klif met klimroutes",
"cs": "Lezecká skála - jediná skála nebo útes s alespoň několika lezeckými cestami",
"es": "Una pared de escalada - una sola roca o acantilado con al menos algunas vías de escalada",
- "ca": "Un cinglera d'escalada - una sola roca o penya-segat amb almenys unes quantes rutes d'escalada"
+ "ca": "Un cinglera d'escalada: una sola roca o penya-segat amb almenys unes quantes rutes d'escalada"
}
},
{
diff --git a/assets/layers/climbing_club/climbing_club.json b/assets/layers/climbing_club/climbing_club.json
index 67729724e2..56a9460894 100644
--- a/assets/layers/climbing_club/climbing_club.json
+++ b/assets/layers/climbing_club/climbing_club.json
@@ -162,7 +162,7 @@
"hu": "Mászószervezet",
"cs": "lezecká nezisková organizace",
"es": "una ONG de escalada",
- "ca": "un ngo d'escalada"
+ "ca": "una ONG d'escalada"
},
"description": {
"de": "Eine Organisation, die sich mit dem Klettern beschäftigt",
@@ -174,7 +174,7 @@
"hu": "Mászással foglalkozó civil szervezet",
"cs": "Nevládní organizace působící v oblasti lezení",
"es": "Una ONG que trabaja en torno a la escalada",
- "ca": "Una ONG que treballa per l'escalada"
+ "ca": "Una ONG que treballa amb l'escalada"
}
}
],
diff --git a/assets/layers/climbing_gym/climbing_gym.json b/assets/layers/climbing_gym/climbing_gym.json
index 63aecdc5a6..220ef5f669 100644
--- a/assets/layers/climbing_gym/climbing_gym.json
+++ b/assets/layers/climbing_gym/climbing_gym.json
@@ -64,7 +64,7 @@
"cs": "Lezecká tělocvična {name}",
"es": "Gimnasio de escalada {name}",
"uk": "Скеледром {name}",
- "ca": "gimnàs d'escalada {name}"
+ "ca": "Gimnàs d'escalada {name}"
}
}
]
@@ -163,7 +163,7 @@
"pl": "Czy można tutaj wypożyczyć buty do wspinaczki?",
"cs": "Lze si zde půjčit lezeckou obuv?",
"es": "¿Se pueden alquilar zapatillas de escalada aquí?",
- "ca": "Es poden llogar sabates d'escalada aquí per utilitzar al gimnàs?"
+ "ca": "Aquí es poden llogar sabates d'escalada per utilitzar al gimnàs?"
},
"mappings": [
{
@@ -180,7 +180,7 @@
"de": "Kletterschuhe können hier kostenlos ausgeliehen werden",
"cs": "Lezeckou obuv si můžete zdarma vypůjčit zde",
"es": "Se pueden pedir prestadas zapatillas de escalada gratis aquí",
- "ca": "Les sabates d'escalada es poden demanar en préstec gratuïtament aquí"
+ "ca": "Aquí es poden demanar en préstec gratuïtament sabates d'escalada"
},
"addExtraTags": [
"service:climbing_shoes:rental:charge="
@@ -219,7 +219,7 @@
"pl": "Można tutaj wypożyczyć buty do wspinaczki",
"cs": "Lezeckou obuv si můžete půjčit zde",
"es": "Se pueden alquilar zapatillas de escalada aquí",
- "ca": "Es poden llogar sabates d'escalada aquí"
+ "ca": "Aquí es poden llogar sabates d'escalada"
},
"addExtraTags": [
"service:climbing_shoes:rental:charge="
@@ -235,7 +235,7 @@
"pl": "Nie można wypożyczyć tutaj butów do wspinaczki",
"cs": "Lezeckou obuv si zde nemůžete zapůjčit",
"es": "No se pueden alquilar zapatillas de escalada aquí",
- "ca": "Les sabates d'escalada poden llogar-se aquí no"
+ "ca": "Aquí no poden llogar-se sabates d'escalada"
},
"addExtraTags": [
"service:climbing_shoes:rental:fee=",
@@ -253,7 +253,7 @@
"de": "Kann man hier einen Klettergurt für die Kletterwand ausleihen?",
"cs": "Lze si zde zapůjčit horolezecký postroj?",
"es": "¿Se puede alquilar un arnés de escalada aquí?",
- "ca": "Es pot llogar un arnès d'escalada aquí per utilitzar al gimnàs?"
+ "ca": "Aquí es pot llogar un arnès d'escalada per utilitzar al gimnàs?"
},
"condition": {
"or": [
@@ -292,7 +292,7 @@
"de": "Ein Klettergurt kann hier kostenlos ausgeliehen werden",
"cs": "Lezecký úvazek si můžete zdarma vypůjčit zde",
"es": "Se puede pedir prestado un arnés de escalada gratis aquí",
- "ca": "Un arnès d'escalada es pot demanar prestat gratuïtament aquí"
+ "ca": "Aquí es pot demanar prestat gratuïtament un arnès d'escalada"
},
"addExtraTags": [
"service:climbing_harness:rental:charge="
@@ -325,7 +325,7 @@
"de": "Ein Klettergurt kann hier ausgeliehen werden",
"cs": "Lezecký postroj si můžete půjčit zde",
"es": "Se puede alquilar un arnés de escalada aquí",
- "ca": "Es pot llogar un arnès d'escalada aquí"
+ "ca": "Aquí es pot llogar un arnès d'escalada"
},
"addExtraTags": [
"service:climbing_harness:rental:fee=",
@@ -341,7 +341,7 @@
"de": "Ein Klettergurt kann hier nicht ausgeliehen werden",
"cs": "Lezecký úvazek si zde nemůžete zapůjčit",
"es": "No se puede alquilar un arnés de escalada aquí",
- "ca": "Un arnés d'escalada pot no ser llogat aquí"
+ "ca": "Aquí no es pot llogar un arnés d'escalada"
},
"addExtraTags": [
"service:climbing_harness:rental:fee=",
@@ -356,7 +356,7 @@
"en": "Are there auto belays for top roping here?",
"nl": "Zijn hier auto belays voor toprope?",
"de": "Gibt es hier Selbstsicherungen für das Toprope-Klettern?",
- "ca": "Hi ha belays automàtics per a la corda superior aquí?"
+ "ca": "Hi ha relleus automàtics per a l'escalada en politja aquí?"
},
"questionHint": {
"en": "Excluding auto belays that are only for speed climbing",
@@ -381,7 +381,7 @@
"en": "There are no auto belays for top roping",
"nl": "Er zijn geen autobelays voor toprope",
"de": "Es gibt keine Selbstsicherungen für das Toprope-Klettern",
- "ca": "No hi ha relleus automàtics per a la corda superior"
+ "ca": "No hi ha asseguraments automàtics per a l'escalada en politja"
}
},
{
@@ -390,7 +390,7 @@
"en": "There are a number of auto belays for top roping",
"nl": "Er zijn enkele autobelays voor toprope",
"de": "Es gibt eine Reihe von Selbstsicherungen für das Toprope-Klettern",
- "ca": "Hi ha una sèrie de relleus automàtics per a la corda superior"
+ "ca": "Hi ha una sèrie d'asseguraments automàtics per a l'escalada en politja"
}
},
{
@@ -399,7 +399,7 @@
"en": "There is an auto belay for every top rope route but manual belaying is also possible",
"nl": "Elke toproperoute kan op autobelay geklommen worden maar handmatig zekeren is ook mogelijk",
"de": "Für jede Toprope-Route gibt es eine Selbstsicherung , aber auch manuelles Sichern ist möglich",
- "ca": "Hi ha un relleu automàtic per a cada ruta de la corda superior, però també és possible el relleu manual"
+ "ca": "Hi ha un assegurament automàtic per a cada ruta d'escalada en politja, però també és possible el relleu manual"
}
},
{
@@ -408,7 +408,7 @@
"en": "Top rope routes can only be climbed on auto belay",
"nl": "Toproperoutes kunnen enkel op autobelay geklommen worden",
"de": "Klettersteige können nur mit Selbstsicherung geklettert werden",
- "ca": "Les rutes de corda més altes només es poden escalar en relleu automàtic"
+ "ca": "Les rutes d'escalada en politja només es poden escalar en relleu automàtic"
}
}
],
@@ -416,7 +416,7 @@
"en": "There are {climbing:autobelay:toprope} auto belay devices for top roping",
"nl": "Er zijn {climbing:autobelay:toprope} autobelaytoestellen voor toprope",
"de": "Es gibt {climbing:autobelay:toprope} Selbstsicherungsgeräte für das Toprope-Klettern",
- "ca": "Hi ha {climbing:autobelay:toprope} dispositius de relleu automàtic per a cordes superiors"
+ "ca": "Hi ha {climbing:autobelay:toprope} dispositius de relleu automàtic per a l'escalada en politja"
}
},
{
@@ -425,7 +425,7 @@
"en": "Are there auto belays for lead climbing here?",
"nl": "Zijn hier autobelays voor voorklimmen?",
"de": "Gibt es hier Selbstsicherungen für das Vorstiegsklettern?",
- "ca": "Hi ha rèpliques automàtiques per a l'escalada de plom?"
+ "ca": "Hi ha asseguraments automàtics per al cap de corda?"
},
"condition": {
"and": [
@@ -444,7 +444,7 @@
"en": "There are no auto belays for lead climbing",
"nl": "Er zijn geen autobelays voor voorklimmen",
"de": "Es gibt keine Selbstsicherungen für das Vorstiegsklettern",
- "ca": "No hi ha relleus automàtics per a l'escalada de plom"
+ "ca": "No hi ha asseguraments automàtics per al cap de corda"
}
},
{
@@ -453,7 +453,7 @@
"en": "There is a number of auto belays for lead climbing",
"nl": "Er zijn enkele autobelays voor voorklimmen",
"de": "Es gibt eine Reihe von Selbstsicherungen für das Vorstiegsklettern",
- "ca": "Hi ha una sèrie de relleus automàtics per a l'escalada de plom"
+ "ca": "Hi ha una sèrie d'asseguraments automàtics per a cada cap de corda"
}
},
{
@@ -462,7 +462,7 @@
"en": "There is an auto belay for every lead climbing route",
"nl": "Elke voorklimroute kan op autobelay geklommen worden",
"de": "Für jede Vorstiegskletterroute gibt es eine Selbstsicherung",
- "ca": "Hi ha un relleu automàtic per a cada ruta d'escalada de plom"
+ "ca": "Hi ha un assegurament automàtic per a cada cap de corda"
}
}
],
@@ -470,7 +470,7 @@
"en": "There are {climbing:autobelay:sport} auto belays for lead climbing",
"nl": "Er zijn {climbing:autobelay:sport} autobelays voor voorklimmen",
"de": "Es gibt {climbing:autobelay:sport} Selbstsicherungen für das Vorstiegsklettern",
- "ca": "Hi ha {climbing:autobelay:sport} relleus automàtics per a l'escalada de plom"
+ "ca": "Hi ha {climbing:autobelay:sport} asseguraments automàtics per al cap de corda"
}
},
{
@@ -482,7 +482,7 @@
"de": "Kann man hier ein Sicherungsgerät für die Kletterwand ausleihen?",
"cs": "Lze si zde půjčit jištění?",
"es": "¿Se puede alquilar un dispositivo de aseguramiento aquí?",
- "ca": "Es pot llogar un aparell de belay aquí per utilitzar al gimnàs?"
+ "ca": "Aquí es pot llogar un aparell d'assegurament per utilitzar al gimnàs?"
},
"condition": {
"or": [
@@ -510,7 +510,7 @@
"de": "Jedes Seil hat ein Sicherungsgerät",
"cs": "U každého lana jsou k dispozici jistící zařízení",
"es": "Se proporcionan dispositivos de aseguramiento en cada cuerda",
- "ca": "Els dispositius Belay es proporcionen a cada corda"
+ "ca": "Els dispositius d'assegurament es proporcionen a cada corda"
},
"addExtraTags": [
"service:climbing_belay_device:rental=",
@@ -532,7 +532,7 @@
"de": "Ein Sicherungsgerät kann hier kostenlos ausgeliehen werden",
"cs": "Jištění si můžete zdarma vypůjčit zde",
"es": "Se puede pedir prestado un dispositivo de aseguramiento gratis aquí",
- "ca": "Un dispositiu d'aspiració es pot demanar prestat gratuïtament aquí"
+ "ca": "Aquí es pot sol·licitar prestat un dispositiu d'assegurament gratuït"
},
"addExtraTags": [
"service:climbing_belay_device:provided_at_each_rope=",
@@ -566,7 +566,7 @@
"de": "Ein Sicherungsgerät kann hier ausgeliehen werden",
"cs": "Jištění si můžete zapůjčit zde",
"es": "Se puede alquilar un dispositivo de aseguramiento aquí",
- "ca": "Es pot llogar un dispositiu d'aspiració aquí"
+ "ca": "Aquí es pot llogar un dispositiu d'assegurament"
},
"addExtraTags": [
"service:climbing_belay_device:provided_at_each_rope=",
@@ -583,7 +583,7 @@
"de": "Ein Sicherungsgerät kann hier nicht ausgeliehen werden",
"cs": "Zde si nelze půjčit jištění",
"es": "No se puede alquilar un dispositivo de aseguramiento aquí",
- "ca": "Un dispositiu de relleu pot llogar no aquí"
+ "ca": "Aquí no es pot llogar un dispositiu d'assegurament"
},
"addExtraTags": [
"service:climbing_belay_device:provided_at_each_rope=",
@@ -602,7 +602,7 @@
"de": "Kann man hier ein Kletterseil für die Kletterwand ausleihen?",
"cs": "Lze si zde půjčit lezecké lano?",
"es": "¿Se puede alquilar una cuerda de escalada aquí?",
- "ca": "Es pot llogar una corda d'escalada aquí per utilitzar al gimnàs?"
+ "ca": "Aquí es pot llogar una corda d'escalada per a utilitzar al gimnàs?"
},
"condition": "climbing:sport!=no",
"mappings": [
@@ -620,7 +620,7 @@
"de": "Ein Kletterseil kann hier kostenlos ausgeliehen werden",
"cs": "Lezecké lano si můžete zdarma vypůjčit zde",
"es": "Se puede pedir prestada una cuerda de escalada gratis aquí",
- "ca": "Una corda d'escalada es pot demanar prestat gratuïtament aquí"
+ "ca": "Aquí es pot demanar prestat gratuïtament una corda d'escalada"
},
"addExtraTags": [
"service:climbing_rope:rental:charge="
@@ -653,7 +653,7 @@
"de": "Ein Kletterseil kann hier ausgeliehen werden",
"cs": "Lezecké lano si můžete půjčit zde",
"es": "Se puede alquilar una cuerda de escalada aquí",
- "ca": "Es pot llogar una corda d'escalada aquí"
+ "ca": "Aquí es pot llogar una corda d'escalada"
},
"addExtraTags": [
"service:climbing_rope:rental:fee=",
@@ -669,7 +669,7 @@
"de": "Ein Kletterseil kann hier nicht ausgeliehen werden",
"cs": "Lezecké lano si zde nemůžete zapůjčit",
"es": "No se puede alquilar una cuerda de escalada aquí",
- "ca": "Es pot llogar una corda d'escalada no aquí"
+ "ca": "Aquí no es pot llogar una corda d'escalada"
},
"addExtraTags": [
"service:climbing_rope:rental:fee=",
@@ -708,7 +708,7 @@
"fr": "Y a-t-il un mur d'escalade de vitesse ?",
"cs": "Je zde rychlostní lezecká stěna?",
"es": "¿Hay una pared de escalada de velocidad?",
- "ca": "Hi ha una paret d'escalada ràpida?"
+ "ca": "Hi ha una paret d'escalada de velocitat?"
},
"mappings": [
{
diff --git a/assets/layers/climbing_route/climbing_route.json b/assets/layers/climbing_route/climbing_route.json
index 67d987b07c..d54ef1bea2 100644
--- a/assets/layers/climbing_route/climbing_route.json
+++ b/assets/layers/climbing_route/climbing_route.json
@@ -206,7 +206,7 @@
"fr": "Cette voie fait {canonical(climbing:length)} de long",
"cs": "Tato trasa je {canonical(climbing:length)} dlouhá",
"es": "Esta vía mide {canonical(climbing:length)} de largo",
- "ca": "Aquesta ruta és {canonical(climbing:length)} llarga"
+ "ca": "Aquesta ruta és {canonical(climbing:length)} de llarg"
},
"freeform": {
"key": "climbing:length",
@@ -234,7 +234,7 @@
"fr": "Selon le système franco-belge, la difficulté de cette voie est de {climbing:grade:french}",
"cs": "Stupeň je {climbing:grade:french} podle francouzského/belgického systému",
"es": "El grado es {climbing:grade:french} según el sistema francés/belga",
- "ca": "La qualificació és {climbing:grade:french} segons el sistema francès/belga"
+ "ca": "El grau és {climbing:grade:french} segons el sistema francès/belga"
},
"freeform": {
"key": "climbing:grade:french"
@@ -251,7 +251,7 @@
"nl": "Hoeveel bouten heeft deze route voordat je het relay bereikt?",
"cs": "Kolik šroubů má tato cesta před dosažením kotvy?",
"es": "¿Cuántos parabolts tiene esta vía antes de llegar al anclaje?",
- "ca": "Quants perns té aquesta ruta abans d'arribar a l'ancoratge?"
+ "ca": "Quants ancoratges d'anella té aquesta ruta abans d'arribar a l'ancoratge?"
},
"render": {
"en": "This route has {climbing:bolts} bolts.
This is without belay stations and indicates how much quickdraws a climber needs.
Això és sense estacions d'assegurament i indica quantes cintes necessita un escalador.
"
},
"max_difficulty": {
- "question": "Quina és la ruta de grau més alt d'aquí, segons el sistema de classificació francès?",
- "render": "La nota més alta és {climbing:grade:french:max} segons el sistema francès/belga"
+ "question": "Quina és la ruta de major aquí, segons el sistema de classificació francès?",
+ "render": "La grau més alt és {climbing:grade:french:max} segons el sistema francès/belga"
},
"min_difficulty": {
- "question": "Quin és el grau de la ruta més fàcil aquí, segons el sistema de classificació francès?",
- "render": "La nota més baixa és {climbing:grade:french:min} segons el sistema francès/belga"
+ "question": "Quin és el grau de la ruta més fàcil aquí segons el sistema de classificació francès?",
+ "render": "El grau més baix és {climbing:grade:french:min} segons el sistema francès/belga"
},
"sportclimbing": {
"mappings": {
@@ -3085,16 +3085,16 @@
"toprope": {
"mappings": {
"0": {
- "then": "L'escalada propícia és possible aquí"
+ "then": "L'escalada en politja és possible aquí"
},
"1": {
- "then": "L'escalada propícia no és possible aquí"
+ "then": "L'escalada en politja no és possible aquí"
},
"2": {
- "then": "Hi ha {climbing:toprope} rutes específiques"
+ "then": "Hi ha {climbing:toprope} rutes d'escalada en politja"
}
},
- "question": "És possible l'escalada propícia aquí?"
+ "question": "És possible l'escalada en politja aquí?"
},
"trad_climbing": {
"mappings": {
@@ -3105,11 +3105,11 @@
"then": "L'escalada tradicional no és possible aquí"
},
"2": {
- "then": "Hi ha {climbing:traditional} vies d'escalada tradicionals"
+ "then": "Hi ha {climbing:traditional} rutes d'escalada tradicionals"
}
},
"question": "És possible l'escalada tradicional aquí?",
- "questionHint": "Utilitzant el vostre propi engranatge, p. ex., chocks"
+ "questionHint": "Utilitzant el vostre propi equipament, p. ex., cales"
},
"website": {
"question": "Hi ha un lloc web (no oficial) amb més informació (p. ex. topos)?"
@@ -3150,7 +3150,7 @@
"then": "Una roca d'escalada: una única roca o penya-segat amb una o unes quantes vies d'escalada que es poden escalar amb seguretat sense corda"
},
"1": {
- "then": "Un cinglera d'escalada - una sola roca o penya-segat amb almenys unes quantes rutes d'escalada"
+ "then": "Un cinglera d'escalada: una sola roca o penya-segat amb almenys unes quantes rutes d'escalada"
},
"2": {
"then": "Una zona d'escalada amb un o més penya-segats i/o roques"
@@ -3170,7 +3170,7 @@
"title": {
"mappings": {
"0": {
- "then": "Trenca d'escalada {name}"
+ "then": "Paret d'escalada {name}"
},
"1": {
"then": "Àrea d'escalada {name}"
@@ -3194,8 +3194,8 @@
"title": "un club d'escalada"
},
"1": {
- "description": "Una ONG que treballa per l'escalada",
- "title": "un ngo d'escalada"
+ "description": "Una ONG que treballa amb l'escalada",
+ "title": "una ONG d'escalada"
}
},
"tagRenderings": {
@@ -3234,78 +3234,78 @@
"then": "Hi ha {climbing:speed} parets d'escalada de velocitat"
}
},
- "question": "Hi ha una paret d'escalada ràpida?"
+ "question": "Hi ha una paret d'escalada de velocitat?"
},
"auto_belay_lead": {
"mappings": {
"0": {
- "then": "No hi ha relleus automàtics per a l'escalada de plom"
+ "then": "No hi ha asseguraments automàtics per al cap de corda"
},
"1": {
- "then": "Hi ha una sèrie de relleus automàtics per a l'escalada de plom"
+ "then": "Hi ha una sèrie d'asseguraments automàtics per a cada cap de corda"
},
"2": {
- "then": "Hi ha un relleu automàtic per a cada ruta d'escalada de plom"
+ "then": "Hi ha un assegurament automàtic per a cada cap de corda"
}
},
- "question": "Hi ha rèpliques automàtiques per a l'escalada de plom?",
- "render": "Hi ha {climbing:autobelay:sport} relleus automàtics per a l'escalada de plom"
+ "question": "Hi ha asseguraments automàtics per al cap de corda?",
+ "render": "Hi ha {climbing:autobelay:sport} asseguraments automàtics per al cap de corda"
},
"auto_belay_toprope": {
"mappings": {
"0": {
- "then": "No hi ha relleus automàtics per a la corda superior"
+ "then": "No hi ha asseguraments automàtics per a l'escalada en politja"
},
"1": {
- "then": "Hi ha una sèrie de relleus automàtics per a la corda superior"
+ "then": "Hi ha una sèrie d'asseguraments automàtics per a l'escalada en politja"
},
"2": {
- "then": "Hi ha un relleu automàtic per a cada ruta de la corda superior, però també és possible el relleu manual"
+ "then": "Hi ha un assegurament automàtic per a cada ruta d'escalada en politja, però també és possible el relleu manual"
},
"3": {
- "then": "Les rutes de corda més altes només es poden escalar en relleu automàtic"
+ "then": "Les rutes d'escalada en politja només es poden escalar en relleu automàtic"
}
},
- "question": "Hi ha belays automàtics per a la corda superior aquí?",
+ "question": "Hi ha relleus automàtics per a l'escalada en politja aquí?",
"questionHint": "Excloent els relleus automàtics que només són per a l'escalada de velocitat",
- "render": "Hi ha {climbing:autobelay:toprope} dispositius de relleu automàtic per a cordes superiors"
+ "render": "Hi ha {climbing:autobelay:toprope} dispositius de relleu automàtic per a l'escalada en politja"
},
"belay_device_rental": {
"mappings": {
"0": {
- "then": "Els dispositius Belay es proporcionen a cada corda"
+ "then": "Els dispositius d'assegurament es proporcionen a cada corda"
},
"1": {
- "then": "Un dispositiu d'aspiració es pot demanar prestat gratuïtament aquí"
+ "then": "Aquí es pot sol·licitar prestat un dispositiu d'assegurament gratuït"
},
"2": {
"then": "Es pot llogar un dispositiu de relleu aquí per {service:climbing_belay_device:rental:charge}"
},
"3": {
- "then": "Es pot llogar un dispositiu d'aspiració aquí"
+ "then": "Aquí es pot llogar un dispositiu d'assegurament"
},
"4": {
- "then": "Un dispositiu de relleu pot llogar no aquí"
+ "then": "Aquí no es pot llogar un dispositiu d'assegurament"
}
},
- "question": "Es pot llogar un aparell de belay aquí per utilitzar al gimnàs?"
+ "question": "Aquí es pot llogar un aparell d'assegurament per utilitzar al gimnàs?"
},
"harness_rental": {
"mappings": {
"0": {
- "then": "Un arnès d'escalada es pot demanar prestat gratuïtament aquí"
+ "then": "Aquí es pot demanar prestat gratuïtament un arnès d'escalada"
},
"1": {
"then": "Es pot llogar un arnès d'escalada aquí per {service:climbing_harness:rental:charge}"
},
"2": {
- "then": "Es pot llogar un arnès d'escalada aquí"
+ "then": "Aquí es pot llogar un arnès d'escalada"
},
"3": {
- "then": "Un arnés d'escalada pot no ser llogat aquí"
+ "then": "Aquí no es pot llogar un arnés d'escalada"
}
},
- "question": "Es pot llogar un arnès d'escalada aquí per utilitzar al gimnàs?"
+ "question": "Aquí es pot llogar un arnès d'escalada per utilitzar al gimnàs?"
},
"name": {
"question": "Quin és el nom d'aquest gimnàs d'escalada?"
@@ -3313,42 +3313,42 @@
"rope_rental": {
"mappings": {
"0": {
- "then": "Una corda d'escalada es pot demanar prestat gratuïtament aquí"
+ "then": "Aquí es pot demanar prestat gratuïtament una corda d'escalada"
},
"1": {
"then": "Es pot llogar una corda d'escalada aquí per {service:climbing_rope:rental:charge}"
},
"2": {
- "then": "Es pot llogar una corda d'escalada aquí"
+ "then": "Aquí es pot llogar una corda d'escalada"
},
"3": {
- "then": "Es pot llogar una corda d'escalada no aquí"
+ "then": "Aquí no es pot llogar una corda d'escalada"
}
},
- "question": "Es pot llogar una corda d'escalada aquí per utilitzar al gimnàs?"
+ "question": "Aquí es pot llogar una corda d'escalada per a utilitzar al gimnàs?"
},
"shoe_rental": {
"mappings": {
"0": {
- "then": "Les sabates d'escalada es poden demanar en préstec gratuïtament aquí"
+ "then": "Aquí es poden demanar en préstec gratuïtament sabates d'escalada"
},
"1": {
"then": "Les sabates d'escalada es poden llogar aquí per {service:climbing_shoes:rental:charge}"
},
"2": {
- "then": "Es poden llogar sabates d'escalada aquí"
+ "then": "Aquí es poden llogar sabates d'escalada"
},
"3": {
- "then": "Les sabates d'escalada poden llogar-se aquí no"
+ "then": "Aquí no poden llogar-se sabates d'escalada"
}
},
- "question": "Es poden llogar sabates d'escalada aquí per utilitzar al gimnàs?"
+ "question": "Aquí es poden llogar sabates d'escalada per utilitzar al gimnàs?"
}
},
"title": {
"mappings": {
"0": {
- "then": "gimnàs d'escalada {name}"
+ "then": "Gimnàs d'escalada {name}"
}
},
"render": "Gimnàs d'escalada"
@@ -3392,11 +3392,11 @@
"tagRenderings": {
"Difficulty": {
"question": "Quin és el grau d'aquesta via d'escalada segons el sistema francès/belga?",
- "render": "La qualificació és {climbing:grade:french} segons el sistema francès/belga"
+ "render": "El grau és {climbing:grade:french} segons el sistema francès/belga"
},
"Length": {
"question": "Quant dura aquesta via d'escalada (en metres)?",
- "render": "Aquesta ruta és {canonical(climbing:length)} llarga"
+ "render": "Aquesta ruta és {canonical(climbing:length)} de llarg"
},
"Name": {
"mappings": {
@@ -3413,11 +3413,11 @@
"bolts": {
"mappings": {
"0": {
- "then": "Aquesta ruta no està vorejada"
+ "then": "Aquesta ruta no té ancoratges d'anella"
}
},
- "question": "Quants perns té aquesta ruta abans d'arribar a l'ancoratge?",
- "render": "Aquesta ruta té {climbing:bolts} perns.
Això no té estacions d'aspiració i indica quant de ràpid necessita un escalador.
"
+ "question": "Quants ancoratges d'anella té aquesta ruta abans d'arribar a l'ancoratge?",
+ "render": "Aquesta ruta té {climbing:bolts} ancoratges d'anella.
Això és sense estacions d'assegurament i indica quantes cintes necessita un escalador.
"
}
},
"title": {
@@ -3443,7 +3443,7 @@
},
"2": {
"description": "Un rellotge visible públicament muntat directament en una paret",
- "title": "un rellotge muntat a la paret, muntat directament en una paret"
+ "title": "un rellotge muntat directament en una paret"
}
},
"tagRenderings": {
@@ -3752,13 +3752,13 @@
"then": "Aquest encreuament no té marques"
},
"1": {
- "then": "Aquest encreuament té marques zebra"
+ "then": "Aquest pas de vianants té marques de zebra"
},
"10": {
- "then": "Aquest encreuament té marques zebra en colors alterns"
+ "then": "Aquest pas de vianants té marques de zebra en colors alterns"
},
"11": {
- "then": "Aquest encreuament té marcacions de doble zebra"
+ "then": "Aquest pas de vianants té marques de zebra doble"
},
"12": {
"then": "Aquest encreuament té pictogrames a la carretera"
@@ -3767,7 +3767,7 @@
"then": "Aquest encreuament té línies a banda i banda de l'encreuament, juntament amb barres que les connecten, amb una interrupció a cada barra"
},
"14": {
- "then": "Aquest encreuament té línies dobles a banda i banda de la travessia"
+ "then": "Aquest encreuament té línies dobles a banda i banda del creuament"
},
"2": {
"then": "Aquest encreuament té marques d'un tipus desconegut"
@@ -3779,23 +3779,23 @@
"then": "Aquest encreuament té línies a banda i banda de l'encreuament, juntament amb barres que els connecten"
},
"5": {
- "then": "Aquest encreuament ha traçat línies a banda i banda de la travessia"
+ "then": "Aquest encreuament té traçades línies a banda i banda de la travessia"
},
"6": {
"then": "Aquest encreuament té línies de punts a banda i banda del encreuament"
},
"7": {
- "then": "Aquest encreuament està marcat per l'ús d'una superfície de color diferent"
+ "then": "Aquest encreuament està marcat usant una superfície de color diferent"
},
"8": {
- "then": "Aquest encreuament té línies a banda i banda de l'encreuament, juntament amb barres angletes que les connecten"
+ "then": "Aquest encreuament té línies a banda i banda de l'encreuament, juntament amb barres en diagonal que les connecten"
},
"9": {
"then": "Aquest encreuament té marques zebra amb una interrupció en cada barra"
}
},
- "question": "Quin tipus de marques té aquest encreuament?",
- "render": "Aquest encreuament té {crossing:markings} marques"
+ "question": "Quin tipus de senyalització té aquest encreuament?",
+ "render": "Aquest encreuament té marques {crossing:markings}"
}
},
"title": {
@@ -3868,7 +3868,7 @@
"then": "Utilitzable per a vehicles tot terreny especialitzats: tractor, ATV"
},
"7": {
- "then": "Impassable / Sense vehicle rodat"
+ "then": "Impassable / Cap vehicle amb rodes"
}
},
"question": "Quina és la suavitat d'aquesta via ciclista?"
@@ -3888,7 +3888,7 @@
"then": "Aquest carril bici està fet de pedra empedrada"
},
"12": {
- "then": "Aquest carril bici està fet de terra crua"
+ "then": "Aquest carril bici està fet de terra"
},
"2": {
"then": "Aquesta via ciclista està feta d'asfalt"
@@ -3956,7 +3956,7 @@
"Surface of the road": {
"mappings": {
"0": {
- "then": "Aquest carril bici no està endurit"
+ "then": "Aquest carril bici no està paviment"
},
"1": {
"then": "Aquest carril bici està pavimentat"
@@ -3968,22 +3968,22 @@
"then": "Aquest carril bici està fet de pedra empedrada"
},
"12": {
- "then": "Aquest carril bici està fet de terra crua"
+ "then": "Aquest carril bici està fet de terra"
},
"2": {
"then": "Aquest carril bici està fet d'asfalt"
},
"3": {
- "then": "Aquest carril bici està fet de llises pedres de paviment"
+ "then": "Aquest carril bici està fet adoquins llisos"
},
"4": {
"then": "Aquest carril bici està fet de formigó"
},
"5": {
- "then": "Aquest carril bici està fet de llamborda (sense mànigues o sett)"
+ "then": "Aquest carril bici està fet de llambordes (sense tallar o carreu)"
},
"6": {
- "then": "Aquest carril bici és de pedra empedrada natural i crua"
+ "then": "Aquest carril bici és de pedra empedrada natural sense tallar"
},
"7": {
"then": "Aquest carril bici és de pedra empedrada plana i quadrada"
@@ -4013,16 +4013,16 @@
"then": "Utilitzable per rodes robustes; Bicicleta de treking, cotxes, bicitaxi"
},
"4": {
- "then": "Utilitzable per a vehicles amb alta habilitació: vehicle off-road lleuger"
+ "then": "Utilitzable per a vehicles amb gran espai lliure al terra: vehicle tot terreny lleuger"
},
"5": {
- "then": "Utilitzable per a vehicles off-road: vehicle off-road de gran consum"
+ "then": "Utilitzable per a vehicles tot terreny: vehicle tot terreny pesat"
},
"6": {
- "then": "Utilitzable per a vehicles especialitzats off-road: tractor, ATV"
+ "then": "Utilitzable per a vehicles tot terreny especialitzats: tractor, quad"
},
"7": {
- "then": "Impassable / Sense vehicle rodat"
+ "then": "Impassable / Cap vehicle amb rodes"
}
},
"question": "Quina és la suavitat d'aquest carrer?"
@@ -4116,34 +4116,34 @@
"then": "Els ciclomotors han d'utilitzar la via ciclista"
},
"1": {
- "then": "Els acceleradors han d'utilitzar la via"
+ "then": "Les bicicletes de pedaleig assistit han d'utilitzar el carril bici"
},
"2": {
- "then": "Els ciclomotors i els acceleradors han d'utilitzar la via"
+ "then": "Els ciclomotors i bicicletes de pedaleig assistit han d'utilitzar la via"
},
"3": {
"then": "Els ciclomotors no estan permesos"
},
"4": {
- "then": "No es permet l'ús de peel·les ràpides"
+ "then": "Les bicicletes de pedaleig assistit no estan permeses"
},
"5": {
- "then": "No es permet l'ús de ciclomotors i acceleradors"
+ "then": "No es permet l'ús de ciclomotors i bicicletes de pedaleig assistit"
},
"6": {
"then": "No hi ha cap senyal de trànsit addicional"
}
},
- "question": "El signe de trànsit D7 () té un signe suplementari?"
+ "question": "El senyal de trànsit D7 () té un senyal suplementari?"
},
"cycleways_and_roads-cycleway:buffer": {
"question": "Quina és la distància entre el carril bici i la carretera?",
- "render": "La memòria intermèdia a més d'aquesta pista és {cycleway:buffer} m"
+ "render": "L'espai junt a aquest carril bici és de {cycleway:buffer} m"
},
"incline": {
"mappings": {
"0": {
- "then": "Hi ha (probablement) cap inclinació aquí"
+ "then": "Probablement aquí no hi ha inclinació"
},
"1": {
"then": "Aquesta carretera té pendent"
@@ -4213,35 +4213,35 @@
},
"cyclist_waiting_aid": {
"description": "Diverses infraestructures que ajuden els ciclistes mentre esperen a un semàfor.",
- "name": "Ciclista que espera ajuda",
+ "name": "Ajudes a l'espera dels ciclistes",
"presets": {
"0": {
"description": "Un reposapeus, barana o altres ajudes, per millorar la comoditat mentre s'espera als semàfors",
- "title": "una ajuda d'espera ciclista"
+ "title": "una ajuda a l'espera del ciclista"
}
},
"tagRenderings": {
"direction": {
"mappings": {
"0": {
- "then": "Aquesta ajuda d'espera es pot utilitzar en avançar d'aquesta manera"
+ "then": "Aquesta ajuda a l'espera es pot utilitzar quan s'avança en aquesta via"
},
"1": {
- "then": "Aquesta ajuda d'espera es pot utilitzar en retrocedir d'aquesta manera"
+ "then": "Aquesta ajuda a l'espera es pot utilitzar quan es retrocedeix per aquest camí"
}
},
- "render": "Aquesta ajuda d'espera es pot utilitzar en anar en direcció {direction}"
+ "render": "Aquesta ajuda a l'espera es pot utilitzar quan es va en direcció {direction}"
},
"side": {
"mappings": {
"0": {
- "then": "Aquesta ajuda d'espera es troba a la banda esquerra"
+ "then": "Aquesta ajuda a l'espera es troba a la banda esquerra"
},
"1": {
- "then": "Aquesta ajuda d'espera es troba al costat dret"
+ "then": "Aquesta ajuda a l'espera es troba al costat dret"
},
"2": {
- "then": "Hi ha ajudes d'espera a banda i banda de la carretera"
+ "then": "Hi ha ajudes a l'espera a ambdós costats de la carretera"
}
},
"question": "A quin costat de la carretera es troba?"
@@ -4252,14 +4252,14 @@
"then": "Hi ha un tauler o una clavilla per descansar el peu aquí"
},
"1": {
- "then": "Hi ha un tren o una nansa per aferrar-se aquí"
+ "then": "Hi ha una barana o una nansa per aferrar-se aquí"
}
},
- "question": "Quin tipus de components té aquesta ajuda d'espera?"
+ "question": "Quin tipus de components té aquesta ajuda a l'espera?"
}
},
"title": {
- "render": "Ciclista esperant ajuda"
+ "render": "Ajuda per a ciclistes en espera"
}
},
"defibrillator": {
@@ -4474,7 +4474,7 @@
}
},
"dog_toilet": {
- "description": "Un vàter de gos és una instal·lació designada per a gossos per orinar i excretar. Aquest pot ser un pegat d'herba designat i senyalitzat, un pou de sorra o una zona tancada.",
+ "description": "Un vàter de gos és una instal·lació designada per a gossos per orinar i excretar. Pot ser un tros d'herba senyalitzat, un pou de sorra o una zona tancada.",
"name": "Vàters per a gossos",
"presets": {
"0": {
@@ -4488,7 +4488,7 @@
"then": "Hi ha una tanca al voltant d'aquest vàter per a gossos"
},
"1": {
- "then": "Hi ha una tanca al voltant d'aquest vàter de gos"
+ "then": "Hi ha una esbardissa al voltant d'aquest vàter de gos"
},
"2": {
"then": "Hi ha una barrera al voltant d'aquest vàter per a gossos"
@@ -4593,7 +4593,7 @@
"then": "Aquesta font d'aigua potable està tancada"
},
"3": {
- "then": "Aquesta aigua potable està tancada permanentment"
+ "then": "Aquesta font d'aigua potable està tancada permanentment"
}
},
"question": "Aquest punt d'aigua potable continua operatiu?",
@@ -4649,16 +4649,16 @@
"then": "Aquí es proporciona aigua freda"
},
"1": {
- "then": "L'aigua freda activa està disponible aquí"
+ "then": "Aquí hi ha aigua refrigerada activament"
},
"2": {
- "then": "L'aigua a temperatura ambient (sense refrigeració activa ni calefacció) està disponible aquí"
+ "then": "L'aigua a temperatura ambient (sense refrigeració ni calefacció activa) està disponible aquí"
},
"3": {
"then": "Aquí es proporciona aigua calenta; l'aigua no és perillosament calenta"
},
"4": {
- "then": "L'aigua calenta es proporciona aquí"
+ "then": "Aquí es proporciona aigua calenta"
}
},
"question": "Hi ha aigua freda aquí?"
@@ -4666,7 +4666,7 @@
"type": {
"mappings": {
"0": {
- "then": "Aquesta és una font de bombolles. Un raig d'aigua per beure s'envia cap amunt, normalment controlat per un botó d'empenta."
+ "then": "Aquesta és una font de raig. Un raig d'aigua per beure s'envia cap amunt, normalment controlat per un botó d'empenta."
},
"1": {
"then": "Aquest és un punt de reomplida d'ampolles on l'aigua s'envia cap avall, normalment controlat per un polsador o un sensor de moviment. Beure directament del raig pot ser molt difícil o impossible."
@@ -4842,7 +4842,7 @@
"then": "Aquest ascensor no té sortida de veu"
}
},
- "question": "Té aquesta sortida de veu d'ascensor?",
+ "question": "Té sortida de veu aquest ascensor?",
"questionHint": "P. e. anuncia la planta actual"
},
"tactile_writing_available": {
@@ -5114,9 +5114,9 @@
"then": "L'origen d'aquest nom és desconegut en tota la literatura"
}
},
- "question": "De què porta aquest objecte?",
+ "question": "A que es deu el nom d'aquest objecte?",
"questionHint": "Això podria estar escrit al cartell del nom del carrer",
- "render": "Anomenat després de {name:etymology}"
+ "render": "Anomenat en honor a {name:etymology}"
},
"street-name-sign-image": {
"render": "{image_carousel(image:streetsign)} {image_upload(image:streetsign, Afegeix una imatge de la placa amb el nom del carrer)}"
@@ -5125,11 +5125,11 @@
"render": "Existeix un article de la Viquipèdia sobre aquest carrer: {wikipedia():max-height:25rem}"
},
"wikipedia-etymology": {
- "question": "Quin és l'element de Wikidata que porta el nom d'aquest objecte?",
+ "question": "Quin és l'element de Wikidata en honor al qual s'anomena aquest objecte?",
"render": "
Article de la Viquipèdia del nom donant
{wikipedia(name:etymology:wikidata):max-height:20rem}"
},
"zoeken op inventaris onroerend erfgoed": {
- "render": "Cerca en inventaris onroerend erfgoed"
+ "render": "Cerca en inventaris onroerend erfgoed"
}
}
},
@@ -5165,7 +5165,7 @@
"0": {
"options": {
"0": {
- "question": "Obert ara"
+ "question": "Ara obert"
}
}
},
@@ -5179,10 +5179,10 @@
"10": {
"options": {
"0": {
- "question": "No hi ha preferència cap als gossos"
+ "question": "Sense preferència pels gossos"
},
"1": {
- "question": "Permesos"
+ "question": "Es permeten gossos"
},
"2": {
"question": "No s'admeten gossos"
@@ -5192,21 +5192,21 @@
"11": {
"options": {
"0": {
- "question": "Ofertes d'internet"
+ "question": "Ofereix internet"
}
}
},
"12": {
"options": {
"0": {
- "question": "Ofertes d'electricitat"
+ "question": "Ofereix electricitat"
}
}
},
"13": {
"options": {
"0": {
- "question": "Té una oferta sense sucre"
+ "question": "Disposa d'oferta sense sucre"
}
}
},
@@ -5220,7 +5220,7 @@
"15": {
"options": {
"0": {
- "question": "Té una oferta lliure de lactosa"
+ "question": "Disposa d'una oferta lliure de lactosa"
}
}
},
@@ -5367,11 +5367,11 @@
},
"firepit": {
"description": "Un lloc a l'aire lliure per fer un foc, normalment obert al públic.",
- "name": "Aixeta",
+ "name": "Foguera",
"presets": {
"0": {
"description": "Un lloc a l'aire lliure per fer un foc, normalment obert al públic.",
- "title": "Aixeta"
+ "title": "Foguera"
}
},
"tagRenderings": {
@@ -5393,19 +5393,19 @@
"then": "Accés només per a clients"
},
"5": {
- "then": "Accés només per autoritzat"
+ "then": "Accés només per a autoritzats"
}
},
"question": "Quin és l'accés permès?"
},
"seasonal": {
"override": {
- "question": "Està disponible la cabina durant tot l'any?"
+ "question": "Està disponible la foguera durant tot l'any?"
}
}
},
"title": {
- "render": "Aixeta"
+ "render": "Foguera"
}
},
"fitness_centre": {
diff --git a/langs/layers/nl.json b/langs/layers/nl.json
index 8ccf620642..094f796b3a 100644
--- a/langs/layers/nl.json
+++ b/langs/layers/nl.json
@@ -2065,9 +2065,6 @@
},
"title": {
"mappings": {
- "0": {
- "then": "{name}"
- },
"1": {
"then": "Vogelkijkhut {name}"
},
@@ -6383,11 +6380,6 @@
}
},
"title": {
- "mappings": {
- "0": {
- "then": "{name}"
- }
- },
"render": "Natuurgebied"
}
},
@@ -6919,21 +6911,6 @@
"render": "Picknicktafel"
}
},
- "play_forest": {
- "description": "Een speelbos is een vrij toegankelijke zone in een bos",
- "name": "Speelbossen",
- "title": {
- "mappings": {
- "0": {
- "then": "{name}"
- },
- "1": {
- "then": "Speelbos {name}"
- }
- },
- "render": "Speelbos"
- }
- },
"playground": {
"deletion": {
"nonDeleteMappings": {
@@ -8587,9 +8564,6 @@
},
"title": {
"mappings": {
- "0": {
- "then": "{name}"
- },
"1": {
"then": "Voetpad"
},
@@ -10755,25 +10729,13 @@
}
},
"village_green": {
- "description": "Een laag die dorpsgroen toont (gemeenschapsgroen, maar niet echt een park)",
- "name": "Speelweide",
- "title": {
- "mappings": {
- "0": {
- "then": "{name}"
- }
- },
- "render": "Speelweide"
- }
+ "description": "Een laag die dorpsgroen toont (gemeenschapsgroen, maar niet echt een park)"
},
"visitor_information_centre": {
"description": "Een bezoekerscentrum biedt informatie over een specifieke attractie of bezienswaardigheid waar het is gevestigd.",
"name": "Bezoekerscentrum",
"title": {
"mappings": {
- "0": {
- "then": "{name:nl}"
- },
"1": {
"then": "{name}"
}
@@ -11003,4 +10965,4 @@
"render": "windturbine"
}
}
-}
\ No newline at end of file
+}
diff --git a/langs/layers/uk.json b/langs/layers/uk.json
index 84dcb0231c..88246580e2 100644
--- a/langs/layers/uk.json
+++ b/langs/layers/uk.json
@@ -838,7 +838,8 @@
"question": "Як називається цей бізнес?",
"render": "Цей бізнес називається {name}"
}
- }
+ },
+ "name": "Кафе та паби"
},
"caravansites": {
"tagRenderings": {
@@ -2999,4 +3000,4 @@
"render": "Утилізація відходів"
}
}
-}
\ No newline at end of file
+}
diff --git a/package-lock.json b/package-lock.json
index ee7c5bddb7..039afe98e5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -47,6 +47,7 @@
"fake-dom": "^1.0.4",
"flowbite-svelte": "^0.47.4",
"follow-redirects": "^1.15.9",
+ "fuse.js": "^7.1.0",
"geojson2svg": "^2.0.2",
"html-to-image": "^1.11.11",
"i18next-client": "^1.11.4",
@@ -15781,6 +15782,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/fuse.js": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz",
+ "integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"dev": true,
@@ -41193,6 +41203,11 @@
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
},
+ "fuse.js": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz",
+ "integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ=="
+ },
"gensync": {
"version": "1.0.0-beta.2",
"dev": true,
diff --git a/package.json b/package.json
index 87869a2070..8a7625ef71 100644
--- a/package.json
+++ b/package.json
@@ -103,6 +103,7 @@
"refresh:layeroverview": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && vite-node scripts/generateLayerOverview.ts -- --force",
"generate:licenses": "vite-node scripts/generateLicenseInfo.ts -- --no-fail",
"query:licenses": "vite-node scripts/generateLicenseInfo.ts -- --query && npm run generate:licenses",
+ "clean:licenses": "find . -type f -name \"*.license\" -exec rm -f {} +",
"generate:contributor-list": "vite-node scripts/generateContributors.ts",
"generate:service-worker": "tsc src/service-worker.ts --outFile public/service-worker.js && git_hash=$(git rev-parse HEAD) && sed -i.bak \"s/GITHUB-COMMIT/$git_hash/\" public/service-worker.js && rm public/service-worker.js.bak",
"reset:layeroverview": "npm run prep:layeroverview && npm run generate:layeroverview && npm run refresh:layeroverview",
@@ -208,6 +209,7 @@
"fake-dom": "^1.0.4",
"flowbite-svelte": "^0.47.4",
"follow-redirects": "^1.15.9",
+ "fuse.js": "^7.1.0",
"geojson2svg": "^2.0.2",
"html-to-image": "^1.11.11",
"i18next-client": "^1.11.4",
diff --git a/public/css/index-tailwind-output.css b/public/css/index-tailwind-output.css
index 0df60cd4cf..908fd6ac44 100644
--- a/public/css/index-tailwind-output.css
+++ b/public/css/index-tailwind-output.css
@@ -1140,10 +1140,6 @@ input[type="range"].range-lg::-moz-range-thumb {
position: absolute;
}
-.\!relative {
- position: relative !important;
-}
-
.relative {
position: relative;
}
@@ -2565,6 +2561,10 @@ input[type="range"].range-lg::-moz-range-thumb {
grid-template-columns: repeat(7, minmax(0, 1fr));
}
+.grid-rows-2 {
+ grid-template-rows: repeat(2, minmax(0, 1fr));
+}
+
.flex-row {
flex-direction: row;
}
@@ -8729,6 +8729,10 @@ svg.apply-fill path {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
+ .md\:grid-rows-1 {
+ grid-template-rows: repeat(1, minmax(0, 1fr));
+ }
+
.md\:flex-row {
flex-direction: row;
}
diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts
index fb727f7d0c..1b76b52233 100644
--- a/scripts/generateLayerOverview.ts
+++ b/scripts/generateLayerOverview.ts
@@ -9,16 +9,12 @@ import {
DoesImageExist,
PrevalidateTheme,
ValidateLayer,
- ValidateThemeEnsemble,
+ ValidateThemeEnsemble
} from "../src/Models/ThemeConfig/Conversion/Validation"
import { Translation } from "../src/UI/i18n/Translation"
import { PrepareLayer } from "../src/Models/ThemeConfig/Conversion/PrepareLayer"
import { PrepareTheme } from "../src/Models/ThemeConfig/Conversion/PrepareTheme"
-import {
- Conversion,
- DesugaringContext,
- DesugaringStep,
-} from "../src/Models/ThemeConfig/Conversion/Conversion"
+import { Conversion, DesugaringContext, DesugaringStep } from "../src/Models/ThemeConfig/Conversion/Conversion"
import { Utils } from "../src/Utils"
import Script from "./Script"
import { AllSharedLayers } from "../src/Customizations/AllSharedLayers"
@@ -267,6 +263,7 @@ class LayerOverviewUtils extends Script {
addWord(lang, tr[lang])
}
}
+
addWord("*", l.id)
addWords(l.title)
addWords(l.description)
@@ -286,9 +283,9 @@ class LayerOverviewUtils extends Script {
| LayerConfigJson
| string
| {
- builtin
- }
- )[]
+ builtin
+ }
+ )[]
}[],
sharedLayers: Map
) {
@@ -317,7 +314,10 @@ class LayerOverviewUtils extends Script {
hideFromOverview: theme.hideFromOverview,
mustHaveLanguage: theme.mustHaveLanguage,
keywords,
- layers: theme.layers.filter((l) => sharedLayers.has(l["id"])).map((l) => l["id"]),
+ layers: (theme.layers)
+ .filter((l) => sharedLayers.has(l.id))
+ .filter(l => l.minzoom < 17)
+ .map((l) => l.id)
}
perId.set(data.id, data)
}
@@ -392,10 +392,10 @@ class LayerOverviewUtils extends Script {
tagRenderings: bootstrapTagRenderings,
tagRenderingOrder: bootstrapTagRenderingsOrder,
sharedLayers: null,
- publicLayers: null,
+ publicLayers: null
},
{
- addTagRenderingsToContext: true,
+ addTagRenderingsToContext: true
}
)
@@ -431,7 +431,7 @@ class LayerOverviewUtils extends Script {
"src/assets/SocialImageBanner.svg",
"src/assets/SocialImageRepo.svg",
"src/assets/svg/osm-logo.svg",
- "src/assets/templates/*",
+ "src/assets/templates/*"
]
for (const path of allSvgs) {
if (
@@ -456,8 +456,8 @@ class LayerOverviewUtils extends Script {
if (contents.indexOf(" 0) {
console.warn(
"The SVG at " +
- path +
- " contains a `text`-tag. This is highly discouraged. Every machine viewing your theme has their own font libary, and the font you choose might not be present, resulting in a different font being rendered. Solution: open your .svg in inkscape (or another program), select the text and convert it to a path"
+ path +
+ " contains a `text`-tag. This is highly discouraged. Every machine viewing your theme has their own font libary, and the font you choose might not be present, resulting in a different font being rendered. Solution: open your .svg in inkscape (or another program), select the text and convert it to a path"
)
errCount++
}
@@ -529,7 +529,7 @@ class LayerOverviewUtils extends Script {
JSON.stringify({
layers: Array.from(sharedLayers.values()).filter(
(l) => !(l["#no-index"] === "yes")
- ),
+ )
})
)
}
@@ -546,11 +546,11 @@ class LayerOverviewUtils extends Script {
// mapcomplete-changes shows an icon for each corresponding mapcomplete-theme
const iconsPerTheme = Array.from(sharedThemes.values()).map((th) => ({
if: "theme=" + th.id,
- then: th.icon,
+ then: th.icon
}))
const proto: ThemeConfigJson = JSON.parse(
readFileSync("./assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json", {
- encoding: "utf8",
+ encoding: "utf8"
})
)
const protolayer = (
@@ -566,7 +566,7 @@ class LayerOverviewUtils extends Script {
new DetectDuplicateFilters().convertStrict(
{
layers: ScriptUtils.getLayerFiles().map((f) => f.parsed),
- themes: ScriptUtils.getThemeFiles().map((f) => f.parsed),
+ themes: ScriptUtils.getThemeFiles().map((f) => f.parsed)
},
ConversionContext.construct([], [])
)
@@ -614,7 +614,7 @@ class LayerOverviewUtils extends Script {
const state: DesugaringContext = {
tagRenderings: LayerOverviewUtils.asDict(sharedTagRenderings),
tagRenderingOrder: sharedTagRenderings.map((tr) => tr.id),
- sharedLayers: AllSharedLayers.getSharedLayersConfigs(),
+ sharedLayers: AllSharedLayers.getSharedLayersConfigs()
}
const sharedLayers = new Map()
const prepLayer = new PrepareLayer(state)
@@ -659,12 +659,12 @@ class LayerOverviewUtils extends Script {
console.log(
"Recompiled layers " +
- recompiledLayers.join(", ") +
- " and skipped " +
- skippedLayers.length +
- " layers. Detected " +
- warningCount +
- " warnings"
+ recompiledLayers.join(", ") +
+ " and skipped " +
+ skippedLayers.length +
+ " layers. Detected " +
+ warningCount +
+ " warnings"
)
// We always need the calculated tags of 'usersettings', so we export them separately
this.extractJavascriptCodeForLayer(
@@ -686,11 +686,11 @@ class LayerOverviewUtils extends Script {
private extractJavascriptCode(themeFile: ThemeConfigJson) {
const allCode = [
"import {Feature} from 'geojson'",
- 'import { ExtraFuncType } from "../../../Logic/ExtraFunctions";',
- 'import { Utils } from "../../../Utils"',
+ "import { ExtraFuncType } from \"../../../Logic/ExtraFunctions\";",
+ "import { Utils } from \"../../../Utils\"",
"export class ThemeMetaTagging {",
" public static readonly themeName = " + JSON.stringify(themeFile.id),
- "",
+ ""
]
for (const layer of themeFile.layers) {
const l = layer
@@ -699,8 +699,8 @@ class LayerOverviewUtils extends Script {
allCode.push(
" public metaTaggging_for_" +
- id +
- "(feat: Feature, helperFunctions: Record Function>) {"
+ id +
+ "(feat: Feature, helperFunctions: Record Function>) {"
)
allCode.push(" const {" + ExtraFunctions.types.join(", ") + "} = helperFunctions")
for (const line of code) {
@@ -711,10 +711,10 @@ class LayerOverviewUtils extends Script {
if (!isStrict) {
allCode.push(
" Utils.AddLazyProperty(feat.properties, '" +
- attributeName +
- "', () => " +
- expression +
- " ) "
+ attributeName +
+ "', () => " +
+ expression +
+ " ) "
)
} else {
attributeName = attributeName.substring(0, attributeName.length - 1).trim()
@@ -754,7 +754,7 @@ class LayerOverviewUtils extends Script {
`/** This code is autogenerated - do not edit. Edit ./assets/layers/${l?.id}/${l?.id}.json instead */`,
"export class ThemeMetaTagging {",
" public static readonly themeName = " + JSON.stringify(l.id),
- "",
+ ""
]
const code = l.calculatedTags ?? []
@@ -769,10 +769,10 @@ class LayerOverviewUtils extends Script {
if (!isStrict) {
allCode.push(
" Utils.AddLazyProperty(feat.properties, '" +
- attributeName +
- "', () => " +
- expression +
- " ) "
+ attributeName +
+ "', () => " +
+ expression +
+ " ) "
)
} else {
attributeName = attributeName.substring(0, attributeName.length - 2).trim()
@@ -813,7 +813,7 @@ class LayerOverviewUtils extends Script {
sharedLayers,
tagRenderings: LayerOverviewUtils.asDict(trs),
tagRenderingOrder: trs.map((tr) => tr.id),
- publicLayers,
+ publicLayers
}
const knownTagRenderings = new Set()
convertState.tagRenderings.forEach((_, key) => knownTagRenderings.add(key))
@@ -870,7 +870,7 @@ class LayerOverviewUtils extends Script {
)
try {
themeFile = new PrepareTheme(convertState, {
- skipDefaultLayers: true,
+ skipDefaultLayers: true
}).convertStrict(
themeFile,
ConversionContext.construct([themePath], ["PrepareLayer"])
@@ -919,7 +919,7 @@ class LayerOverviewUtils extends Script {
const e: string = [
`the icon for theme ${themeFile.id} is too small. Please rescale the icon at ${themeFile.icon}`,
`Even though an SVG is 'infinitely scaleable', the icon should be dimensioned bigger. One of the build steps of the theme does convert the image to a PNG (to serve as PWA-icon) and having a small dimension will cause blurry images.`,
- ` Width = ${width} height = ${height}; we recommend a size of at least 500px * 500px and to use a square aspect ratio.`,
+ ` Width = ${width} height = ${height}; we recommend a size of at least 500px * 500px and to use a square aspect ratio.`
].join("\n")
err(e)
}
@@ -956,7 +956,7 @@ class LayerOverviewUtils extends Script {
hideFromOverview: t.hideFromOverview ?? false,
shortDescription:
t.shortDescription ?? new Translation(t.description).FirstSentence(),
- mustHaveLanguage: t.mustHaveLanguage?.length > 0,
+ mustHaveLanguage: t.mustHaveLanguage?.length > 0
}
}),
sharedLayers
@@ -965,10 +965,10 @@ class LayerOverviewUtils extends Script {
console.log(
"Recompiled themes " +
- recompiledThemes.join(", ") +
- " and skipped " +
- skippedThemes.length +
- " themes"
+ recompiledThemes.join(", ") +
+ " and skipped " +
+ skippedThemes.length +
+ " themes"
)
return fixed
diff --git a/src/Logic/FeatureSource/Sources/ThemeSource.ts b/src/Logic/FeatureSource/Sources/ThemeSource.ts
index e06b694c18..fc79e477a6 100644
--- a/src/Logic/FeatureSource/Sources/ThemeSource.ts
+++ b/src/Logic/FeatureSource/Sources/ThemeSource.ts
@@ -50,6 +50,7 @@ export default class ThemeSource implements IndexedFeatureSource {
const features = (this.features = new UIEventSource([]))
const featuresById = (this.featuresById = new UIEventSource(new Map()))
this.core = mvtAvailableLayers.mapD((mvtAvailableLayers) => {
+ this.core?.data?.destruct()
const core = new ThemeSourceCore(
layers,
featureSwitches,
@@ -300,4 +301,9 @@ class ThemeSourceCore extends FeatureSourceMerger {
// await Promise.all(this.supportsForceDownload.map((i) => i.updateAsync()))
console.log("Done")
}
+
+ public destruct() {
+ this.features.destroy()
+ this.featuresById.destroy()
+ }
}
diff --git a/src/Logic/Search/ThemeSearch.ts b/src/Logic/Search/ThemeSearch.ts
index 13f8d3e510..9bf6bf8277 100644
--- a/src/Logic/Search/ThemeSearch.ts
+++ b/src/Logic/Search/ThemeSearch.ts
@@ -1,19 +1,109 @@
import ThemeConfig, { MinimalThemeInformation } from "../../Models/ThemeConfig/ThemeConfig"
import { Store } from "../UIEventSource"
import UserRelatedState from "../State/UserRelatedState"
-import { Utils } from "../../Utils"
-import Locale from "../../UI/i18n/Locale"
import themeOverview from "../../assets/generated/theme_overview.json"
-import LayerSearch from "./LayerSearch"
-import SearchUtils from "./SearchUtils"
import { OsmConnection } from "../Osm/OsmConnection"
import { AndroidPolyfill } from "../Web/AndroidPolyfill"
+import Fuse from "fuse.js"
+import Constants from "../../Models/Constants"
+import Locale from "../../UI/i18n/Locale"
+import { Utils } from "../../Utils"
-type ThemeSearchScore = {
- theme: MinimalThemeInformation
- lowest: number
- perLayer?: Record
- other: number
+
+export class ThemeSearchIndex {
+
+ private readonly themeIndex: Fuse
+ private readonly layerIndex: Fuse<{ id: string, description }>
+
+ constructor(language: string, themesToSearch?: MinimalThemeInformation[], layersToIgnore: string[] = []) {
+ const themes = Utils.NoNull(themesToSearch ?? ThemeSearch.officialThemes?.themes)
+ if (!themes) {
+ throw "No themes loaded. Did generate:layeroverview fail?"
+ }
+ const fuseOptions = {
+ ignoreLocation: true,
+ threshold: 0.2,
+ keys: [
+ { name: "id", weight: 2 },
+ "title." + language,
+ "keywords." + language,
+ "shortDescription." + language
+ ]
+ }
+
+ this.themeIndex = new Fuse(themes.filter(th => th?.id !== "personal"), fuseOptions)
+
+ const toIgnore = new Set(layersToIgnore)
+ const layersAsList: { id: string, description: Record }[] = []
+ for (const id in ThemeSearch.officialThemes.layers) {
+ if (Constants.isPriviliged(id)) {
+ continue
+ }
+ if (toIgnore.has(id)) {
+ continue
+ }
+ const l: Record = ThemeSearch.officialThemes.layers[id]
+ layersAsList.push({ id, description: l })
+ }
+ this.layerIndex = new Fuse(layersAsList, {
+ includeScore: true,
+ minMatchCharLength: 3,
+ ignoreLocation: true,
+ threshold: 0.02,
+ keys: ["id", "description." + language]
+ })
+ }
+
+ public search(text: string, limit?: number): MinimalThemeInformation[] {
+ const scored = this.searchWithScores(text)
+ let result = Array.from(scored.entries())
+ result.sort((a, b) => b[0] - a[0])
+ if (limit) {
+ result = result.slice(0, limit)
+ }
+ return result.map(e => ThemeSearch.officialThemesById.get(e[0]))
+ }
+
+ public searchWithScores(text: string): Map {
+ const result = new Map()
+ const themeResults = this.themeIndex.search(text)
+ for (const themeResult of themeResults) {
+ result.set(themeResult.item.id, themeResult.score)
+ }
+
+ const layerResults = this.layerIndex.search(text)
+
+ for (const layer of layerResults) {
+ const matchingThemes = ThemeSearch.layersToThemes.get(layer.item.id)
+ const score = layer.score
+ matchingThemes?.forEach(th => {
+ const previous = result.get(th.id) ?? 10000
+ result.set(th.id, Math.min(previous, score * 5))
+ })
+ }
+
+
+ return result
+ }
+
+ /**
+ * Builds a search index containing all public and visited themes, but ignoring the layers loaded by the current theme
+ */
+ public static fromState(state: { osmConnection: OsmConnection; theme: ThemeConfig }): Store {
+ const layersToIgnore = state.theme.layers.filter((l) => l.isNormal()).map((l) => l.id)
+ const knownHidden: Store = UserRelatedState.initDiscoveredHiddenThemes(
+ state.osmConnection
+ ).map((list) => Utils.Dedup(list))
+ const otherThemes: MinimalThemeInformation[] = ThemeSearch.officialThemes.themes.filter(
+ (th) => th.id !== state.theme.id
+ )
+ return Locale.language.map(language => {
+ const themes = otherThemes.concat(...knownHidden.data.map(id => ThemeSearch.officialThemesById.get(id)))
+ return new ThemeSearchIndex(language, themes, layersToIgnore)
+ },
+ [knownHidden]
+ )
+ }
}
export default class ThemeSearch {
@@ -25,42 +115,26 @@ export default class ThemeSearch {
string,
MinimalThemeInformation
>()
+
+
+ /*
+ * For every layer id, states which themes use the layer
+ */
+ public static readonly layersToThemes: Map = new Map()
static {
for (const th of ThemeSearch.officialThemes.themes ?? []) {
ThemeSearch.officialThemesById.set(th.id, th)
+ for (const layer of th.layers) {
+ let list = ThemeSearch.layersToThemes.get(layer)
+ if (!list) {
+ list = []
+ ThemeSearch.layersToThemes.set(layer, list)
+ }
+ list.push(th)
+ }
}
}
- private readonly _knownHiddenThemes: Store>
- private readonly _layersToIgnore: string[]
- private readonly _otherThemes: MinimalThemeInformation[]
-
- constructor(state: { osmConnection: OsmConnection; theme: ThemeConfig }) {
- this._layersToIgnore = state.theme.layers.filter((l) => l.isNormal()).map((l) => l.id)
- this._knownHiddenThemes = UserRelatedState.initDiscoveredHiddenThemes(
- state.osmConnection
- ).map((list) => new Set(list))
- this._otherThemes = ThemeSearch.officialThemes.themes.filter(
- (th) => th.id !== state.theme.id
- )
- }
-
- public search(query: string, limit: number, threshold: number = 3): MinimalThemeInformation[] {
- if (query.length < 1) {
- return []
- }
- const sorted = ThemeSearch.sortedByLowestScores(
- query,
- this._otherThemes,
- this._layersToIgnore
- )
- return sorted
- .filter((sorted) => sorted.lowest < threshold)
- .map((th) => th.theme)
- .filter((th) => !th.hideFromOverview || this._knownHiddenThemes.data.has(th.id))
- .slice(0, limit)
- }
-
public static createUrlFor(layout: { id: string }, state?: { layoutToUse?: { id } }): string {
if (layout === undefined) {
return undefined
@@ -97,82 +171,5 @@ export default class ThemeSearch {
return `${linkPrefix}`
}
- /**
- * Returns a score based on textual search
- *
- * Note that, if `query.length < 3`, layers are _not_ searched because this takes too much time
- * @param query
- * @param themes
- * @param ignoreLayers
- * @private
- */
- private static scoreThemes(
- query: string,
- themes: MinimalThemeInformation[],
- ignoreLayers: string[] = undefined
- ): Record {
- if (query?.length < 1) {
- return undefined
- }
- themes = Utils.NoNullInplace(themes)
- let options: { blacklist: Set } = undefined
- if (ignoreLayers?.length > 0) {
- options = { blacklist: new Set(ignoreLayers) }
- }
- const layerScores = query.length < 3 ? {} : LayerSearch.scoreLayers(query, options)
- const results: Record = {}
- for (const layoutInfo of themes) {
- const theme = layoutInfo.id
- if (theme === "personal") {
- continue
- }
- if (Utils.simplifyStringForSearch(theme) === query) {
- results[theme] = {
- theme: layoutInfo,
- lowest: -1,
- other: 0,
- }
- continue
- }
- const perLayer = Utils.asRecord(layoutInfo.layers ?? [], (layer) => layerScores[layer])
- const language = Locale.language.data
-
- const keywords = Utils.NoNullInplace([
- layoutInfo.shortDescription,
- layoutInfo.title,
- ]).map((item) => (typeof item === "string" ? item : item[language] ?? item["*"]))
-
- const other = Math.min(
- SearchUtils.scoreKeywords(query, keywords),
- SearchUtils.scoreKeywords(query, layoutInfo.keywords)
- )
- const lowest = Math.min(other, ...Object.values(perLayer))
- results[theme] = {
- theme: layoutInfo,
- perLayer,
- other,
- lowest,
- }
- }
- return results
- }
-
- public static sortedByLowestScores(
- search: string,
- themes: MinimalThemeInformation[],
- ignoreLayers: string[] = []
- ): ThemeSearchScore[] {
- const scored = Object.values(this.scoreThemes(search, themes, ignoreLayers))
- scored.sort((a, b) => a.lowest - b.lowest)
- return scored
- }
-
- public static sortedByLowest(
- search: string,
- themes: MinimalThemeInformation[],
- ignoreLayers: string[] = []
- ): MinimalThemeInformation[] {
- return this.sortedByLowestScores(search, themes, ignoreLayers).map((th) => th.theme)
- }
}
diff --git a/src/Logic/State/LayerState.ts b/src/Logic/State/LayerState.ts
index c1e9578ce6..88bb507836 100644
--- a/src/Logic/State/LayerState.ts
+++ b/src/Logic/State/LayerState.ts
@@ -8,7 +8,6 @@ import Translations from "../../UI/i18n/Translations"
import { RegexTag } from "../Tags/RegexTag"
import { Or } from "../Tags/Or"
import FilterConfig from "../../Models/ThemeConfig/FilterConfig"
-import Constants from "../../Models/Constants"
export type ActiveFilter = {
layer: LayerConfig
diff --git a/src/Logic/State/SearchState.ts b/src/Logic/State/SearchState.ts
index 1d01737957..e4bf83bba1 100644
--- a/src/Logic/State/SearchState.ts
+++ b/src/Logic/State/SearchState.ts
@@ -4,7 +4,7 @@ import CombinedSearcher from "../Search/CombinedSearcher"
import FilterSearch, { FilterSearchResult } from "../Search/FilterSearch"
import LocalElementSearch from "../Search/LocalElementSearch"
import CoordinateSearch from "../Search/CoordinateSearch"
-import ThemeSearch from "../Search/ThemeSearch"
+import { ThemeSearchIndex } from "../Search/ThemeSearch"
import OpenStreetMapIdSearch from "../Search/OpenStreetMapIdSearch"
import PhotonSearch from "../Search/PhotonSearch"
import ThemeViewState from "../../Models/ThemeViewState"
@@ -67,8 +67,8 @@ export default class SearchState {
Stores.concat(suggestions).map((suggestions) => CombinedSearcher.merge(suggestions))
)
- const themeSearch = new ThemeSearch(state)
- this.themeSuggestions = this.searchTerm.mapD((query) => themeSearch.search(query, 3))
+ const themeSearch = ThemeSearchIndex.fromState(state)
+ this.themeSuggestions = this.searchTerm.mapD((query) => themeSearch.data.search(query, 3), [themeSearch])
const layerSearch = new LayerSearch(state.theme)
this.layerSuggestions = this.searchTerm.mapD((query) => layerSearch.search(query, 5))
diff --git a/src/Logic/UIEventSource.ts b/src/Logic/UIEventSource.ts
index 88b5dc953d..4b892bb714 100644
--- a/src/Logic/UIEventSource.ts
+++ b/src/Logic/UIEventSource.ts
@@ -626,11 +626,9 @@ class MappedStore extends Store {
}
private registerCallbacksToUpstream() {
- const self = this
-
- this._unregisterFromUpstream = this._upstream.addCallback((_) => self.update())
+ this._unregisterFromUpstream = this._upstream.addCallback((_) => this.update())
this._unregisterFromExtraStores = this._extraStores?.map((store) =>
- store?.addCallback((_) => self.update())
+ store?.addCallback((_) => this.update())
)
this._callbacksAreRegistered = true
}
diff --git a/src/Models/ThemeViewState/WithImageState.ts b/src/Models/ThemeViewState/WithImageState.ts
index 54c3311cd4..63843f07d7 100644
--- a/src/Models/ThemeViewState/WithImageState.ts
+++ b/src/Models/ThemeViewState/WithImageState.ts
@@ -1,6 +1,5 @@
import { ImageUploadManager } from "../../Logic/ImageProviders/ImageUploadManager"
-import { Store, UIEventSource } from "../../Logic/UIEventSource"
-import { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider"
+import { Store } from "../../Logic/UIEventSource"
import { CombinedFetcher } from "../../Logic/Web/NearbyImagesSearch"
import ThemeConfig from "../ThemeConfig/ThemeConfig"
import { PanoramaxUploader } from "../../Logic/ImageProviders/Panoramax"
@@ -13,7 +12,6 @@ import { SpecialVisualizationState } from "../../UI/SpecialVisualization"
export class WithImageState extends WithGuiState implements SpecialVisualizationState {
readonly imageUploadManager: ImageUploadManager
- readonly previewedImage = new UIEventSource(undefined)
readonly nearbyImageSearcher: CombinedFetcher
constructor(layout: ThemeConfig, mvtAvailableLayers: Store>) {
diff --git a/src/Models/ThemeViewState/WithSelectedElementState.ts b/src/Models/ThemeViewState/WithSelectedElementState.ts
index 6f00dc570d..bb30f0d54b 100644
--- a/src/Models/ThemeViewState/WithSelectedElementState.ts
+++ b/src/Models/ThemeViewState/WithSelectedElementState.ts
@@ -45,7 +45,7 @@ export class WithSelectedElementState extends UserMapFeatureswitchState {
selected?.properties?.name,
selected?.properties?.alt_name,
selected?.properties?.local_name,
- layer?.title.GetRenderValue(selected?.properties ?? {}).txt,
+ layer?.title?.GetRenderValue(selected?.properties ?? {})?.txt,
selected.properties.display_name,
selected.properties.id,
]
diff --git a/src/UI/AllThemesGui.svelte b/src/UI/AllThemesGui.svelte
index ca745216b1..aad6262cc5 100644
--- a/src/UI/AllThemesGui.svelte
+++ b/src/UI/AllThemesGui.svelte
@@ -18,15 +18,16 @@
import Mastodon from "../assets/svg/Mastodon.svelte"
import Liberapay from "../assets/svg/Liberapay.svelte"
import Bug from "../assets/svg/Bug.svelte"
- import Github from "../assets/svg/Github.svelte"
import { Utils } from "../Utils"
import { ArrowTrendingUp } from "@babeard/svelte-heroicons/solid/ArrowTrendingUp"
import Searchbar from "./Base/Searchbar.svelte"
- import ThemeSearch from "../Logic/Search/ThemeSearch"
+ import ThemeSearch, { ThemeSearchIndex } from "../Logic/Search/ThemeSearch"
import SearchUtils from "../Logic/Search/SearchUtils"
import ChevronDoubleRight from "@babeard/svelte-heroicons/mini/ChevronDoubleRight"
import { AndroidPolyfill } from "../Logic/Web/AndroidPolyfill"
import Forgejo from "../assets/svg/Forgejo.svelte"
+ import Locale from "./i18n/Locale"
+
AndroidPolyfill.init().then(() => console.log("Android polyfill setup completed"))
const featureSwitches = new OsmConnectionFeatureSwitches()
const osmConnection = new OsmConnection({
@@ -35,13 +36,15 @@
"oauth_token",
undefined,
"Used to complete the login"
- ),
+ )
})
const state = new UserRelatedState(osmConnection)
const t = Translations.t.index
const tu = Translations.t.general
const tr = Translations.t.general.morescreen
+ const recentThemes = state.recentlyVisitedThemes.value.mapD(themes => themes.map(thId => ThemeSearch.officialThemesById.get(thId)))
+
let userLanguages = osmConnection.userDetails.map((ud) => ud?.languages ?? [])
let search: UIEventSource = new UIEventSource("")
let searchStable = search.stabilized(100)
@@ -64,30 +67,28 @@
const customThemes: Store = Stores.ListStabilized(
state.installedUserThemes
).mapD((stableIds) => Utils.NoNullInplace(stableIds.map((id) => state.getUnofficialTheme(id))))
+
function filtered(themes: Store): Store {
+ const searchIndex = Locale.language.map(language => {
+ return new ThemeSearchIndex(language, themes.data)
+ }, [themes])
+
+
return searchStable.map(
- (search) => {
+ (searchTerm) => {
if (!themes.data) {
return []
}
- if (!search) {
+ if (!searchTerm) {
return themes.data
}
- const start = new Date().getTime()
- const scores = ThemeSearch.sortedByLowestScores(search, themes.data)
- const end = new Date().getTime()
- console.trace("Scores for", search, "are", scores, "searching took", end - start, "ms")
- const strict = scores.filter((sc) => sc.lowest < 2)
- if (strict.length > 0) {
- return strict.map((sc) => sc.theme)
- }
- return scores
- .filter((sc) => sc.lowest < 4)
- .slice(0, 6)
- .map((sc) => sc.theme)
+ const index = searchIndex.data
+
+ return index.search(searchTerm)
+
},
- [themes]
+ [searchIndex]
)
}
@@ -100,7 +101,7 @@
let customSearched: Store = filtered(customThemes)
let searchIsFocussed = new UIEventSource(false)
- document.addEventListener("keydown", function (event) {
+ document.addEventListener("keydown", function(event) {
if (event.ctrlKey && event.code === "KeyF") {
searchIsFocussed.set(true)
event.preventDefault()
@@ -165,6 +166,17 @@
+
+ {#if $recentThemes.length > 2}
+
+
+
+
+
+
+ {/if}
+
+
- import { ImmutableStore, Store } from "../../Logic/UIEventSource"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import type { MinimalThemeInformation } from "../../Models/ThemeConfig/ThemeConfig"
import Tr from "../Base/Tr.svelte"
@@ -10,7 +9,7 @@
export let theme: MinimalThemeInformation & { isOfficial?: boolean }
let isCustom: boolean = theme.id.startsWith("https://") || theme.id.startsWith("http://")
export let state: { layoutToUse?: { id: string }; osmConnection: OsmConnection }
-
+ export let iconOnly: boolean = false
$: title = Translations.T(
theme.title,
!isCustom && !theme.mustHaveLanguage ? "themes:" + theme.id + ".title" : undefined
@@ -71,12 +70,17 @@
)
-
-
-
-
-
diff --git a/src/UI/Map/ShowDataLayer.ts b/src/UI/Map/ShowDataLayer.ts
index 15aa40d70f..710891da7a 100644
--- a/src/UI/Map/ShowDataLayer.ts
+++ b/src/UI/Map/ShowDataLayer.ts
@@ -352,6 +352,11 @@ class LineRenderingLayer {
// After waiting 'till the map has loaded, the data might have changed already
// As such, we only now read the features from the featureSource and compare with the previously set data
const features = featureSource.data
+ if (features.length === 0) {
+ // This is a very ugly workaround for https://source.mapcomplete.org/MapComplete/MapComplete/issues/2312,
+ // but I couldn't find the root cause
+ return
+ }
const src = map.getSource(this._layername)
{
// Add source to the map or update the feature source
diff --git a/src/UI/SpecialVisualisations/UISpecialVisualisations.ts b/src/UI/SpecialVisualisations/UISpecialVisualisations.ts
index 598ceac70f..55ab2a23c4 100644
--- a/src/UI/SpecialVisualisations/UISpecialVisualisations.ts
+++ b/src/UI/SpecialVisualisations/UISpecialVisualisations.ts
@@ -29,7 +29,7 @@ class QuestionViz implements SpecialVisualizationSvelte {
},
{
name: "blacklisted-labels",
- doc: "One or more ';'-separated labels of questions which should _not_ be included",
+ doc: "One or more ';'-separated labels of questions which should _not_ be included. Default: 'hidden'"
},
]
svelteBased = true
@@ -46,10 +46,13 @@ class QuestionViz implements SpecialVisualizationSvelte {
?.split(";")
?.map((s) => s.trim())
?.filter((s) => s !== "")
- const blacklist = args[1]
+ const blacklist = (args[1])
?.split(";")
?.map((s) => s.trim())
?.filter((s) => s !== "")
+ if (blacklist.length === 0) {
+ blacklist.push("hidden")
+ }
return new SvelteUIElement(Questionbox, {
layer,
tags,
diff --git a/src/assets/svg/Github.svelte b/src/assets/svg/Github.svelte
deleted file mode 100644
index 39cfc12040..0000000000
--- a/src/assets/svg/Github.svelte
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
\ No newline at end of file