From 60e337ed19deab80f4a25f5b191cb32f3e2abb73 Mon Sep 17 00:00:00 2001 From: Pau Nofuentes Date: Thu, 13 Feb 2025 22:23:47 +0000 Subject: [PATCH 01/22] Translated using Weblate (Catalan) Currently translated at 81.5% (3408 of 4181 strings) Translation: MapComplete/layers Translate-URL: https://translate.mapcomplete.org/projects/mapcomplete/layers/ca/ --- langs/layers/ca.json | 228 +++++++++++++++++++++---------------------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/langs/layers/ca.json b/langs/layers/ca.json index 1b127473756..d4da26052fd 100644 --- a/langs/layers/ca.json +++ b/langs/layers/ca.json @@ -3057,16 +3057,16 @@ "render": "S'ha de pagar una tarifa de {charge} per a escalar aquí" }, "max_bolts": { - "question": "Quants parabolts tenen com a màxim les rutes a {title()} ?", + "question": "Quants ancoratges d'anella tenen com a màxim les rutes a {title()} ?", "render": "Les rutes d'escalada esportiva aquí tenen com a màxim {climbing:bolts:max} perns.
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(escalada: longitud)} llarga" + "render": "Aquesta ruta té {canonical(escalada: longitud)} 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": { @@ -13630,4 +13630,4 @@ "render": "Turbina eòlica" } } -} \ No newline at end of file +} From 5030f3116b3f1e8c7763e303dfd42f0d8be759dc Mon Sep 17 00:00:00 2001 From: Pau Nofuentes Date: Thu, 13 Feb 2025 23:38:39 +0000 Subject: [PATCH 02/22] Translated using Weblate (Spanish) Currently translated at 91.4% (3823 of 4181 strings) Translation: MapComplete/layers Translate-URL: https://translate.mapcomplete.org/projects/mapcomplete/layers/es/ --- langs/layers/es.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/langs/layers/es.json b/langs/layers/es.json index b55421284ee..60cb4b4d567 100644 --- a/langs/layers/es.json +++ b/langs/layers/es.json @@ -4027,7 +4027,7 @@ "presets": { "0": { "description": "Reposapiés, pasamanos u otro tipo de ayuda para mejorar la comodidad durante la espera en los semáforos", - "title": "un ciclista espera ayuda" + "title": "una ayuda a la espera del ciclista" } }, "tagRenderings": { @@ -12617,4 +12617,4 @@ "render": "aerogenerador" } } -} \ No newline at end of file +} From bd366da16b97548efa7acb82d0ca6c39b89511d9 Mon Sep 17 00:00:00 2001 From: Weblate Date: Fri, 14 Feb 2025 17:32:59 +0100 Subject: [PATCH 03/22] Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: MapComplete/layers Translate-URL: https://translate.mapcomplete.org/projects/mapcomplete/layers/ --- langs/layers/nl.json | 42 ++---------------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/langs/layers/nl.json b/langs/layers/nl.json index 8ccf6206426..094f796b3a2 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 +} From 2f9c14512645a2f09ca0c872f3be3f7f49023754 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Fri, 14 Feb 2025 17:34:03 +0100 Subject: [PATCH 04/22] Chore: translation sync --- assets/layers/climbing/climbing.json | 22 +++---- .../layers/climbing_area/climbing_area.json | 4 +- .../layers/climbing_club/climbing_club.json | 4 +- assets/layers/climbing_gym/climbing_gym.json | 60 +++++++++---------- .../layers/climbing_route/climbing_route.json | 10 ++-- assets/layers/clock/clock.json | 2 +- assets/layers/crossings/crossings.json | 18 +++--- .../cycleways_and_roads.json | 36 +++++------ .../cyclist_waiting_aid.json | 22 +++---- assets/layers/dog_toilet/dog_toilet.json | 4 +- .../layers/drinking_water/drinking_water.json | 10 ++-- assets/layers/elevator/elevator.json | 2 +- assets/layers/etymology/etymology.json | 8 +-- assets/layers/filters/filters.json | 14 ++--- assets/layers/firepit/firepit.json | 10 ++-- langs/layers/ca.json | 2 +- langs/layers/es.json | 2 +- langs/layers/nl.json | 42 ++++++++++++- 18 files changed, 155 insertions(+), 117 deletions(-) diff --git a/assets/layers/climbing/climbing.json b/assets/layers/climbing/climbing.json index 0bbedac561f..d5580174e5e 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 160355b59f1..f9cb91e6f84 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 67729724e26..56a94608948 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 63aecdc5a6f..220ef5f6698 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 67d987b07c8..5ca1a90acf9 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(escalada: longitud)} 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.
", @@ -260,7 +260,7 @@ "it": "Questo percorso ha {climbing:bolts} bulloni
Questa è senza collettori e indica di quanti bloccaggi rapidi ha bisogno un arrampicatore
", "nl": "Deze route heeft {climbing:bolts} haken.
Hierbij wordt de standplaats niet meegeteld. Een klimmer heeft normaal gezien dus minstens {climbing:bolts} setjes nodig.
", "es": "Esta vía tiene {climbing:bolts} parabolts
Esto es sin reuniones e indica cuántos cintas exprés necesita un escalador
", - "ca": "Aquesta ruta té {climbing:bolts} perns.
Això no té estacions d'aspiració i indica quant de ràpid necessita un escalador.
" + "ca": "Aquesta ruta té {climbing:bolts} ancoratges d'anella.
Això és sense estacions d'assegurament i indica quantes cintes necessita un escalador.
" }, "freeform": { "key": "climbing:bolts", @@ -281,7 +281,7 @@ "nl": "Deze route heeft geen bouten", "cs": "Tato trasa není vyšroubovaná", "es": "Esta vía no tiene parabolts", - "ca": "Aquesta ruta no està vorejada" + "ca": "Aquesta ruta no té ancoratges d'anella" }, "addExtraTags": [ "climbing:bolts=" diff --git a/assets/layers/clock/clock.json b/assets/layers/clock/clock.json index 566a98f923e..66b7b9fae5d 100644 --- a/assets/layers/clock/clock.json +++ b/assets/layers/clock/clock.json @@ -135,7 +135,7 @@ "de": "eine Wanduhr, die direkt an der Wand angebracht ist", "es": "un reloj, montado directamente en una pared", "cs": "nástěnné hodiny, namontované přímo na stěnu", - "ca": "un rellotge muntat a la paret, muntat directament en una paret" + "ca": "un rellotge muntat directament en una paret" }, "description": { "en": "A publicly visible clock mounted directly on a wall", diff --git a/assets/layers/crossings/crossings.json b/assets/layers/crossings/crossings.json index 421213d3c57..733613c4535 100644 --- a/assets/layers/crossings/crossings.json +++ b/assets/layers/crossings/crossings.json @@ -235,7 +235,7 @@ "nl": "Wat voor markering heeft deze oversteekplaats?", "de": "Welche Art von Markierungen gibt es an diesem Übergang?", "es": "¿Qué tipo de señalización tiene este cruce?", - "ca": "Quin tipus de marques té aquest encreuament?" + "ca": "Quin tipus de senyalització té aquest encreuament?" }, "mappings": [ { @@ -261,7 +261,7 @@ "de": "Dieser Übergang ist mit Zebrastreifen markiert", "es": "Este paso de cebra está señalizado", "cs": "Tento přechod má označení zebra", - "ca": "Aquest encreuament té marques zebra" + "ca": "Aquest pas de vianants té marques de zebra" }, "icon": { "class": "large", @@ -318,7 +318,7 @@ "de": "Dieser Übergang hat gestrichelte Linien auf beiden Seiten des Übergangs", "es": "Este cruce tiene líneas discontinuas a ambos lados del cruce", "cs": "Tento přechod má po obou stranách přerušované čáry", - "ca": "Aquest encreuament ha traçat línies a banda i banda de la travessia" + "ca": "Aquest encreuament té traçades línies a banda i banda de la travessia" }, "icon": { "class": "large", @@ -347,7 +347,7 @@ "nl": "Deze oversteekplaats is gemarkeerd door een anders gekleurd wegdek", "de": "Dieser Übergang wird durch eine andersfarbige Oberfläche gekennzeichnet", "es": "Este cruce se marca utilizando una superficie de color diferente", - "ca": "Aquest encreuament està marcat per l'ús d'una superfície de color diferent" + "ca": "Aquest encreuament està marcat usant una superfície de color diferent" }, "icon": { "class": "large", @@ -361,7 +361,7 @@ "nl": "Deze oversteekplaats heeft lijnen aan beide kanten van de oversteekplaats, met schuine strepen die ze verbinden", "de": "Diese Kreuzung hat Linien auf beiden Seiten der Kreuzung, zusammen mit abgewinkelten Stangen, die sie verbinden", "es": "Este cruce tiene líneas a ambos lados, junto con barras en ángulo que las conectan", - "ca": "Aquest encreuament té línies a banda i banda de l'encreuament, juntament amb barres angletes que les connecten" + "ca": "Aquest encreuament té línies a banda i banda de l'encreuament, juntament amb barres en diagonal que les connecten" }, "icon": { "class": "large", @@ -386,7 +386,7 @@ "de": "Dieser Übergang hat Zebrastreifen in wechselnden Farben", "es": "Este paso tiene marcas de cebra en colores alternos", "cs": "Tento přechod má označení zebry ve střídavých barvách", - "ca": "Aquest encreuament té marques zebra en colors alterns" + "ca": "Aquest pas de vianants té marques de zebra en colors alterns" }, "icon": { "class": "large", @@ -401,7 +401,7 @@ "de": "Dieser Übergang hat doppelte Zebrastreifen", "es": "Este paso de cebra tiene doble señalización", "cs": "Tento přechod má dvojité značení zebry", - "ca": "Aquest encreuament té marcacions de doble zebra" + "ca": "Aquest pas de vianants té marques de zebra doble" }, "icon": { "class": "large", @@ -438,7 +438,7 @@ "de": "Dieser Übergang hat doppelte Linien auf beiden Seiten des Übergangs", "es": "Este cruce tiene líneas dobles a cada lado del cruce", "cs": "Tento přechod má dvojité čáry na obou stranách přechodu", - "ca": "Aquest encreuament té línies dobles a banda i banda de la travessia" + "ca": "Aquest encreuament té línies dobles a banda i banda del creuament" }, "icon": { "class": "large", @@ -451,7 +451,7 @@ "nl": "Deze oversteekplaats heeft {crossing:markings} markeringen", "de": "Dieser Übergang hat {crossing:markings} Markierungen", "es": "Este cruce tiene marcas {crossing:markings}", - "ca": "Aquest encreuament té {crossing:markings} marques" + "ca": "Aquest encreuament té marques {crossing:markings}" }, "freeform": { "key": "crossing:markings", diff --git a/assets/layers/cycleways_and_roads/cycleways_and_roads.json b/assets/layers/cycleways_and_roads/cycleways_and_roads.json index 89dd8c579af..9e9b9dabc36 100644 --- a/assets/layers/cycleways_and_roads/cycleways_and_roads.json +++ b/assets/layers/cycleways_and_roads/cycleways_and_roads.json @@ -799,7 +799,7 @@ "es": "Este carril bici está hecho de tierra", "fr": "Cette piste cyclable est faite en sol brut", "cs": "Tato cyklostezka je vyrobena ze surové zeminy", - "ca": "Aquest carril bici està fet de terra crua" + "ca": "Aquest carril bici està fet de terra" } } ], @@ -842,7 +842,7 @@ "de": "Hier gibt es (wahrscheinlich) keine Steigung", "nl": "De straat heeft hier (waarschijnlijk) geen helling", "es": "Probablemente no hay inclinación aquí", - "ca": "Hi ha (probablement) cap inclinació aquí" + "ca": "Probablement aquí no hi ha inclinació" }, "hideInAnswer": true }, @@ -976,7 +976,7 @@ "fr": "Impasse / Aucun véhicule roulant", "cs": "Neprůjezdné / Zákaz vjezdu vozidel", "es": "Intransitable / Ningún vehículo con ruedas", - "ca": "Impassable / Sense vehicle rodat" + "ca": "Impassable / Cap vehicle amb rodes" } } ], @@ -1006,7 +1006,7 @@ "fr": "Cette piste cycable est non durcie", "cs": "Tato cyklostezka není zpevněná", "es": "Este carril bici no está pavimentado", - "ca": "Aquest carril bici no està endurit" + "ca": "Aquest carril bici no està paviment" }, "hideInAnswer": true }, @@ -1047,7 +1047,7 @@ "fr": "Cette piste cyclable est faite en pavés lisses", "cs": "Tato cyklostezka je tvořena hladkými dlažebními kostkami", "es": "Este carril bici está hecho de adoquines lisos", - "ca": "Aquest carril bici està fet de llises pedres de paviment" + "ca": "Aquest carril bici està fet adoquins llisos" } }, { @@ -1073,7 +1073,7 @@ "fr": "Cette piste cyclable est faite de pavés (taillé ou non)", "cs": "Tato cyklostezka je vyrobena z dlážděného kamene (netesaného nebo vydlabaného)", "es": "Este carril bici está hecho de adoquines (sin labrar o de sillería)", - "ca": "Aquest carril bici està fet de llamborda (sense mànigues o sett)" + "ca": "Aquest carril bici està fet de llambordes (sense tallar o carreu)" }, "hideInAnswer": true }, @@ -1087,7 +1087,7 @@ "fr": "Cette piste cyclable est en pavés bruts et naturels", "cs": "Tato cyklostezka je vyrobena ze surového přírodního dlažebního kamene", "es": "Este carril bici está hecho de adoquines naturales sin labrar", - "ca": "Aquest carril bici és de pedra empedrada natural i crua" + "ca": "Aquest carril bici és de pedra empedrada natural sense tallar" } }, { @@ -1164,7 +1164,7 @@ "fr": "Cette piste cyclable est faite en sol brut", "cs": "Tato cyklostezka je vyrobena ze surové půdy", "es": "Este carril bici está hecho de tierra", - "ca": "Aquest carril bici està fet de terra crua" + "ca": "Aquest carril bici està fet de terra" } } ], @@ -1258,7 +1258,7 @@ "fr": "Utilisable pour les véhicules à dégagement élevé : véhicule tout-terrain léger", "cs": "Použitelné pro vozidla s vysokou světlou výškou: lehké terénní vozidlo", "es": "Utilizable para vehículos con altura libre al suelo alta: vehículo todoterreno ligero", - "ca": "Utilitzable per a vehicles amb alta habilitació: vehicle off-road lleuger" + "ca": "Utilitzable per a vehicles amb gran espai lliure al terra: vehicle tot terreny lleuger" } }, { @@ -1271,7 +1271,7 @@ "fr": "Utilisable pour les véhicules tout-terrain : véhicule tout-terrain lourd", "cs": "Použitelné pro terénní vozidla: těžké terénní vozidlo", "es": "Utilizable para vehículos todoterreno: vehículo todoterreno pesado", - "ca": "Utilitzable per a vehicles off-road: vehicle off-road de gran consum" + "ca": "Utilitzable per a vehicles tot terreny: vehicle tot terreny pesat" } }, { @@ -1284,7 +1284,7 @@ "fr": "Utilisable pour les véhicules hors route spécialisés : tracteur, véhicule 4x4", "cs": "Použitelný pro specializované terénní vozy: traktor, čtyřkolka", "es": "Utilizable para vehículos todoterreno especializados: tractor, ATV", - "ca": "Utilitzable per a vehicles especialitzats off-road: tractor, ATV" + "ca": "Utilitzable per a vehicles tot terreny especialitzats: tractor, quad" } }, { @@ -1296,7 +1296,7 @@ "fr": "Impasse / Aucun véhicule roulant", "cs": "Neprůjezdné / Pro vozidla", "es": "Intransitable / Ningún vehículo con ruedas", - "ca": "Impassable / Sense vehicle rodat" + "ca": "Impassable / Cap vehicle amb rodes" } } ], @@ -1675,7 +1675,7 @@ "fr": "Le panneau de signalisation D7 () a-t-il un panneau supplémentaire ?", "cs": "Má dopravní značka D7 () doplňkovou značku?", "es": "¿Tiene la señal de tráfico D7 () una señal complementaria?", - "ca": "El signe de trànsit D7 () té un signe suplementari?" + "ca": "El senyal de trànsit D7 () té un senyal suplementari?" }, "condition": { "or": [ @@ -1713,7 +1713,7 @@ "fr": "Les VAE (Vélo à Assistance Electrique) rapides doivent utiliser la piste cyclable", "cs": "Rychlá Elektrokola musí používat cyklostezku", "es": "Las bicicletas de pedaleo asistido deben usar el carril bici", - "ca": "Els acceleradors han d'utilitzar la via" + "ca": "Les bicicletes de pedaleig assistit han d'utilitzar el carril bici" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -1733,7 +1733,7 @@ "fr": "Les cyclomoteurs et les VAE doivent utiliser la piste cyclable", "cs": "Mopedy a rychlá elektrokola musí používat cyklostezku", "es": "Los ciclomotores y las bicicletas de pedaleo asistido deben usar el carril bici", - "ca": "Els ciclomotors i els acceleradors han d'utilitzar la via" + "ca": "Els ciclomotors i bicicletes de pedaleig assistit han d'utilitzar la via" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -1774,7 +1774,7 @@ "fr": "Les VAE ne sont pas autorisés", "cs": "Rychlá elektrokola nejsou povoleny", "es": "Las bicicletas de pedaleo asistido no están permitidas", - "ca": "No es permet l'ús de peel·les ràpides" + "ca": "Les bicicletes de pedaleig assistit no estan permeses" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -1794,7 +1794,7 @@ "fr": "Les cyclomoteurs et les VAE ne sont pas autorisés", "cs": "Mopedy a rychlá elektrokola nejsou povoleny", "es": "Los ciclomotores y las bicicletas de pedaleo asistido no están permitidos", - "ca": "No es permet l'ús de ciclomotors i acceleradors" + "ca": "No es permet l'ús de ciclomotors i bicicletes de pedaleig assistit" }, "hideInAnswer": "_country!=be", "addExtraTags": [ @@ -1827,7 +1827,7 @@ "de": "Der Sicherheitsabstand zu diesem Radweg beträgt {cycleway:buffer} m", "cs": "Nárazník vedle této cyklostezky je {cycleway:buffer} m", "es": "El espacio junto a este carril bici es de {cycleway:buffer} m", - "ca": "La memòria intermèdia a més d'aquesta pista és {cycleway:buffer} m" + "ca": "L'espai junt a aquest carril bici és de {cycleway:buffer} m" }, "question": { "en": "How wide is the gap between the cycleway and the road?", diff --git a/assets/layers/cyclist_waiting_aid/cyclist_waiting_aid.json b/assets/layers/cyclist_waiting_aid/cyclist_waiting_aid.json index 75ba3452d79..7f510035903 100644 --- a/assets/layers/cyclist_waiting_aid/cyclist_waiting_aid.json +++ b/assets/layers/cyclist_waiting_aid/cyclist_waiting_aid.json @@ -4,7 +4,7 @@ "en": "Cyclist Waiting Aids", "de": "Radfahrer-Wartehilfen", "es": "Ayudas a la espera de ciclistas", - "ca": "Ciclista que espera ajuda" + "ca": "Ajudes a l'espera dels ciclistes" }, "description": { "en": "Various pieces of infrastructure that aid cyclists while they wait at a traffic light.", @@ -21,7 +21,7 @@ "de": "Radfahrer-Wartehilfe", "es": "Ayuda para ciclistas en espera", "nl": "Steuntje voor wachtende fietsers", - "ca": "Ciclista esperant ajuda" + "ca": "Ajuda per a ciclistes en espera" } }, "pointRendering": [ @@ -54,7 +54,7 @@ "en": "a cyclist waiting aid", "de": "eine Radfahrer-Wartehilfe", "es": "un ciclista espera ayuda", - "ca": "una ajuda d'espera ciclista" + "ca": "una ajuda a l'espera del ciclista" }, "tags": [ "highway=cyclist_waiting_aid" @@ -77,7 +77,7 @@ "en": "What kind of components does this waiting aid have?", "de": "Aus welchen Bestandteilen besteht diese Wartehilfe?", "es": "¿Qué tipo de componentes tiene esta ayuda a la espera?", - "ca": "Quin tipus de components té aquesta ajuda d'espera?" + "ca": "Quin tipus de components té aquesta ajuda a l'espera?" }, "id": "type", "multiAnswer": true, @@ -98,7 +98,7 @@ "en": "There is a rail or a handle to hold on to here", "de": "Hier gibt es eine Schiene oder einen Griff zum Festhalten", "es": "Hay una barandilla o un asa para agarrarse aquí", - "ca": "Hi ha un tren o una nansa per aferrar-se aquí" + "ca": "Hi ha una barana o una nansa per aferrar-se aquí" }, "ifnot": "handrest=" } @@ -119,7 +119,7 @@ "en": "This waiting aid is located on the left side", "de": "Diese Wartehilfe befindet sich auf der linken Seite", "es": "Esta ayuda a la espera se encuentra en el lado izquierdo", - "ca": "Aquesta ajuda d'espera es troba a la banda esquerra" + "ca": "Aquesta ajuda a l'espera es troba a la banda esquerra" } }, { @@ -128,7 +128,7 @@ "en": "This waiting aid is located on the right side", "de": "Diese Wartehilfe befindet sich auf der rechten Seite", "es": "Esta ayuda a la espera se encuentra en el lado derecho", - "ca": "Aquesta ajuda d'espera es troba al costat dret" + "ca": "Aquesta ajuda a l'espera es troba al costat dret" } }, { @@ -137,7 +137,7 @@ "en": "There are waiting aids on both sides of the road", "de": "Auf beiden Seiten der Straße gibt es Wartehilfen", "es": "Hay ayudas a la espera a ambos lados de la carretera", - "ca": "Hi ha ajudes d'espera a banda i banda de la carretera" + "ca": "Hi ha ajudes a l'espera a ambdós costats de la carretera" } } ] @@ -152,7 +152,7 @@ "en": "This waiting aid can be used when going forward on this way", "de": "Diese Wartehilfe kann bei der Weiterfahrt auf diesem Weg genutzt werden", "es": "Esta ayuda a la espera puede utilizarse cuando se avanza por esta vía", - "ca": "Aquesta ajuda d'espera es pot utilitzar en avançar d'aquesta manera" + "ca": "Aquesta ajuda a l'espera es pot utilitzar quan s'avança en aquesta via" } }, { @@ -161,7 +161,7 @@ "en": "This waiting aid can be used when going backward on this way", "de": "Diese Wartehilfe kann beim Rückwärtsfahren auf diesem Weg benutzt werden", "es": "Esta ayuda a la espera puede utilizarse cuando se retrocede por este camino", - "ca": "Aquesta ajuda d'espera es pot utilitzar en retrocedir d'aquesta manera" + "ca": "Aquesta ajuda a l'espera es pot utilitzar quan es retrocedeix per aquest camí" } } ], @@ -169,7 +169,7 @@ "en": "This waiting aid can be used when going in {direction} direction", "de": "Diese Wartehilfe kann in Fahrtrichtung {direction} benutzt werden", "es": "Esta ayuda a la espera puede utilizarse cuando se va en dirección {direction}", - "ca": "Aquesta ajuda d'espera es pot utilitzar en anar en direcció {direction}" + "ca": "Aquesta ajuda a l'espera es pot utilitzar quan es va en direcció {direction}" } } ], diff --git a/assets/layers/dog_toilet/dog_toilet.json b/assets/layers/dog_toilet/dog_toilet.json index 4d78a5ce256..bdaa87a3df4 100644 --- a/assets/layers/dog_toilet/dog_toilet.json +++ b/assets/layers/dog_toilet/dog_toilet.json @@ -9,7 +9,7 @@ "description": { "en": "A dog toilet is a facility designated for dogs to urinate and excrete. This can be a designated, signposted patch of grass, a sand pit or a fenced area.", "de": "Eine Hundetoilette ist eine Einrichtung, die für das Urinieren und die Ausscheidung von Hunden vorgesehen ist. Dabei kann es sich um eine ausgewiesene, ausgeschilderte Rasenfläche, eine Sandgrube oder einen eingezäunten Bereich handeln.", - "ca": "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." + "ca": "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." }, "source": { "osmTags": "amenity=dog_toilet" @@ -76,7 +76,7 @@ "then": { "en": "There is a hedge around this dog toilet", "de": "Diese Hundetoilette ist von einer Hecke umgeben", - "ca": "Hi ha una tanca al voltant d'aquest vàter de gos" + "ca": "Hi ha una esbardissa al voltant d'aquest vàter de gos" } }, { diff --git a/assets/layers/drinking_water/drinking_water.json b/assets/layers/drinking_water/drinking_water.json index 782d6c03315..300cb5ba76d 100644 --- a/assets/layers/drinking_water/drinking_water.json +++ b/assets/layers/drinking_water/drinking_water.json @@ -244,7 +244,7 @@ "de": "Die Trinkwasserstelle ist dauerhaft geschlossen", "uk": "Цей пункт питної води постійно закритий", "es": "Esta fuente de agua potable está cerrada permanentemente", - "ca": "Aquesta aigua potable està tancada permanentment" + "ca": "Aquesta font d'aigua potable està tancada permanentment" } } ], @@ -305,7 +305,7 @@ "de": "Dies ist ein Sprudelbrunnen. Ein Wasserstrahl zum Trinken wird nach oben gerichtet und in der Regel durch einen Druckknopf gesteuert.", "uk": "Це барботажний фонтан. Струмінь води, з якого можна пити, спрямовується вгору, зазвичай керується кнопкою.", "es": "Esta es una fuente de chorro. Un chorro de agua para beber se envía hacia arriba, típicamente controlado por un botón.", - "ca": "Aquesta és una font de bombolles. Un raig d'aigua per beure s'envia cap amunt, normalment controlat per un botó d'empenta." + "ca": "Aquesta és una font de raig. Un raig d'aigua per beure s'envia cap amunt, normalment controlat per un botó d'empenta." }, "addExtraTags": [ "man_made=" @@ -419,7 +419,7 @@ "en": "Actively cooled water is available here", "nl": "Afgekoeld water is hier beschikbaar", "de": "Hier steht aktiv gekühltes Wasser zur Verfügung", - "ca": "L'aigua freda activa està disponible aquí" + "ca": "Aquí hi ha aigua refrigerada activament" } }, { @@ -429,7 +429,7 @@ "en": "Ambient temperature water (without active cooling or heating) is available here", "nl": "Water aan omgevingstemperatuur (zonder actieve koeling of opwarming) is hier beschikbaar", "de": "Wasser mit Umgebungstemperatur (ohne aktive Kühlung oder Heizung) ist hier verfügbar", - "ca": "L'aigua a temperatura ambient (sense refrigeració activa ni calefacció) està disponible aquí" + "ca": "L'aigua a temperatura ambient (sense refrigeració ni calefacció activa) està disponible aquí" } }, { @@ -449,7 +449,7 @@ "en": "Hot water is provided here", "nl": "Heet water is hier beschikbaar", "de": "Hier wird heißes Wasser bereitgestellt", - "ca": "L'aigua calenta es proporciona aquí" + "ca": "Aquí es proporciona aigua calenta" } } ] diff --git a/assets/layers/elevator/elevator.json b/assets/layers/elevator/elevator.json index b5bdd8142fc..db439b770c4 100644 --- a/assets/layers/elevator/elevator.json +++ b/assets/layers/elevator/elevator.json @@ -390,7 +390,7 @@ "cs": "Má tento výtah hlasový výstup?", "es": "¿Tiene este ascensor salida de voz?", "nl": "Heeft deze lift spraakuitvoer?", - "ca": "Té aquesta sortida de veu d'ascensor?" + "ca": "Té sortida de veu aquest ascensor?" }, "questionHint": { "en": "E.g. it announces the current floor", diff --git a/assets/layers/etymology/etymology.json b/assets/layers/etymology/etymology.json index 957b2a4962a..f5c91424e25 100644 --- a/assets/layers/etymology/etymology.json +++ b/assets/layers/etymology/etymology.json @@ -122,7 +122,7 @@ "da": "Hvilket Wikidata-emne er dette objekt opkaldt efter?", "es": "¿Cuál es el elemento de Wikidata en honor a el cual se nombra este objeto?", "uk": "На честь якого елемента Вікіданих названо цей об'єкт?", - "ca": "Quin és l'element de Wikidata que porta el nom d'aquest objecte?" + "ca": "Quin és l'element de Wikidata en honor al qual s'anomena aquest objecte?" }, "freeform": { "key": "name:etymology:wikidata", @@ -272,7 +272,7 @@ "fr": "Chercher sur inventaris onroerend erfgoed", "cs": "Hledání na inventaris onroerend erfgoed", "es": "Buscar en Inventaris Onroerend Erfgoed", - "ca": "Cerca en inventaris onroerend erfgoed" + "ca": "Cerca en inventaris onroerend erfgoed" }, "condition": "_country=be" }, @@ -287,7 +287,7 @@ "cs": "Po čem je tento objekt pojmenován?", "da": "Hvad er dette objekt opkaldt efter?", "es": "¿A qué se debe el nombre de este objeto?", - "ca": "De què porta aquest objecte?" + "ca": "A que es deu el nom d'aquest objecte?" }, "render": { "en": "Named after {name:etymology}", @@ -298,7 +298,7 @@ "pl": "Nazwane po {name:etymology}", "cs": "Pojmenováno po {name:etymology}", "es": "Nombrado en honor a {name:etymology}", - "ca": "Anomenat després de {name:etymology}" + "ca": "Anomenat en honor a {name:etymology}" }, "freeform": { "key": "name:etymology", diff --git a/assets/layers/filters/filters.json b/assets/layers/filters/filters.json index 7d1581a8a57..e53fd8245c5 100644 --- a/assets/layers/filters/filters.json +++ b/assets/layers/filters/filters.json @@ -14,7 +14,7 @@ "en": "Now open", "nl": "Nu open", "de": "Jetzt geöffnet", - "ca": "Obert ara", + "ca": "Ara obert", "es": "Abierto ahora", "fr": "Ouvert maintenant", "hu": "Most nyitva van", @@ -289,7 +289,7 @@ "de": "Keine Bevorzugung von Hunden", "cs": "Bez preference psů", "es": "Sin preferencia por los perros", - "ca": "No hi ha preferència cap als gossos" + "ca": "Sense preferència pels gossos" } }, { @@ -299,7 +299,7 @@ "de": "Hunde erlaubt", "cs": "Psi povoleny", "es": "Se permiten perros", - "ca": "Permesos" + "ca": "Es permeten gossos" }, "emoji": "🐕", "osmTags": { @@ -333,7 +333,7 @@ "de": "Internetzugang vorhanden", "cs": "Nabízí internet", "es": "Ofrece internet", - "ca": "Ofertes d'internet" + "ca": "Ofereix internet" }, "icon": "wifi", "osmTags": { @@ -355,7 +355,7 @@ "de": "Stromanschluss vorhanden", "cs": "Nabízí elektřinu", "es": "Ofrece electricidad", - "ca": "Ofertes d'electricitat" + "ca": "Ofereix electricitat" }, "osmTags": "service:electricity=yes" } @@ -370,7 +370,7 @@ "cs": "Má nabídku bez cukru", "de": "Hat zuckerfreie Angebote", "es": "Tiene una oferta sin azúcar", - "ca": "Té una oferta sense sucre" + "ca": "Disposa d'oferta sense sucre" }, "osmTags": { "or": [ @@ -413,7 +413,7 @@ "cs": "Má nabídku bez laktózy", "de": "Hat laktosefreie Angebote", "es": "Tiene una oferta sin lactosa", - "ca": "Té una oferta lliure de lactosa" + "ca": "Disposa d'una oferta lliure de lactosa" }, "icon": "./assets/layers/questions/lactose_free.svg", "osmTags": { diff --git a/assets/layers/firepit/firepit.json b/assets/layers/firepit/firepit.json index f6fe15f04e4..e0ca43740f6 100644 --- a/assets/layers/firepit/firepit.json +++ b/assets/layers/firepit/firepit.json @@ -4,7 +4,7 @@ "en": "Firepit", "de": "Feuerstelle", "es": "Hoguera", - "ca": "Aixeta" + "ca": "Foguera" }, "description": { "en": "An outdoor place to make a fire, typically open to the public.", @@ -21,7 +21,7 @@ "en": "Firepit", "de": "Feuerstelle", "es": "Hoguera", - "ca": "Aixeta" + "ca": "Foguera" } }, "titleIcons": [ @@ -52,7 +52,7 @@ "en": "Firepit", "de": "Feuerstelle", "es": "Hoguera", - "ca": "Aixeta" + "ca": "Foguera" }, "description": { "de": "Eine Stelle im Freien zum Feuermachen, typischerweise öffentlich zugänglich.", @@ -127,7 +127,7 @@ "de": "Zugang nur für Berechtigte", "en": "Access only for authorized", "es": "Acceso solo para autorizados", - "ca": "Accés només per autoritzat" + "ca": "Accés només per a autoritzats" } } ] @@ -140,7 +140,7 @@ "nl": "Is deze kampvuurplaats heel het jaar door beschikbaar?", "de": "Ist diese Feuerstelle rund um das Jahr nutzbar?", "es": "¿Está la hoguera disponible todo el año?", - "ca": "Està disponible la cabina durant tot l'any?" + "ca": "Està disponible la foguera durant tot l'any?" } } } diff --git a/langs/layers/ca.json b/langs/layers/ca.json index 361d7f367a4..99f9d23b430 100644 --- a/langs/layers/ca.json +++ b/langs/layers/ca.json @@ -13630,4 +13630,4 @@ "render": "Turbina eòlica" } } -} +} \ No newline at end of file diff --git a/langs/layers/es.json b/langs/layers/es.json index 8bb75904d6a..b55421284ee 100644 --- a/langs/layers/es.json +++ b/langs/layers/es.json @@ -12617,4 +12617,4 @@ "render": "aerogenerador" } } -} +} \ No newline at end of file diff --git a/langs/layers/nl.json b/langs/layers/nl.json index 094f796b3a2..8ccf6206426 100644 --- a/langs/layers/nl.json +++ b/langs/layers/nl.json @@ -2065,6 +2065,9 @@ }, "title": { "mappings": { + "0": { + "then": "{name}" + }, "1": { "then": "Vogelkijkhut {name}" }, @@ -6380,6 +6383,11 @@ } }, "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, "render": "Natuurgebied" } }, @@ -6911,6 +6919,21 @@ "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": { @@ -8564,6 +8587,9 @@ }, "title": { "mappings": { + "0": { + "then": "{name}" + }, "1": { "then": "Voetpad" }, @@ -10729,13 +10755,25 @@ } }, "village_green": { - "description": "Een laag die dorpsgroen toont (gemeenschapsgroen, maar niet echt een park)" + "description": "Een laag die dorpsgroen toont (gemeenschapsgroen, maar niet echt een park)", + "name": "Speelweide", + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "Speelweide" + } }, "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}" } @@ -10965,4 +11003,4 @@ "render": "windturbine" } } -} +} \ No newline at end of file From cdb050261e7d0ea6fd13099689f6e9b91c35cfb8 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Fri, 14 Feb 2025 21:36:21 +0100 Subject: [PATCH 05/22] Chore: Fix broken translation --- assets/layers/climbing_route/climbing_route.json | 2 +- langs/layers/ca.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/layers/climbing_route/climbing_route.json b/assets/layers/climbing_route/climbing_route.json index 5ca1a90acf9..d54ef1bea29 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(escalada: longitud)} de llarg" + "ca": "Aquesta ruta és {canonical(climbing:length)} de llarg" }, "freeform": { "key": "climbing:length", diff --git a/langs/layers/ca.json b/langs/layers/ca.json index 99f9d23b430..831969ed730 100644 --- a/langs/layers/ca.json +++ b/langs/layers/ca.json @@ -3396,7 +3396,7 @@ }, "Length": { "question": "Quant dura aquesta via d'escalada (en metres)?", - "render": "Aquesta ruta és {canonical(escalada: longitud)} de llarg" + "render": "Aquesta ruta és {canonical(climbing:length)} de llarg" }, "Name": { "mappings": { From 2e5e1166c8df47d878fc3a74da17d51dbcb4ee43 Mon Sep 17 00:00:00 2001 From: mike140 Date: Fri, 14 Feb 2025 22:18:47 +0000 Subject: [PATCH 06/22] Translated using Weblate (Ukrainian) Currently translated at 19.1% (801 of 4181 strings) Translation: MapComplete/layers Translate-URL: https://translate.mapcomplete.org/projects/mapcomplete/layers/uk/ --- langs/layers/uk.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/langs/layers/uk.json b/langs/layers/uk.json index 84dcb0231c9..88246580e28 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 +} From 9de9f55327c2db3f18e0c11f66ba7a796080269e Mon Sep 17 00:00:00 2001 From: Weblate Date: Sat, 15 Feb 2025 21:03:10 +0100 Subject: [PATCH 07/22] Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: MapComplete/layers Translate-URL: https://translate.mapcomplete.org/projects/mapcomplete/layers/ --- langs/layers/nl.json | 42 ++---------------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/langs/layers/nl.json b/langs/layers/nl.json index 8ccf6206426..094f796b3a2 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 +} From 1723f268c03fdb7b49df99c5c0ae587892eebc7d Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sat, 15 Feb 2025 23:42:07 +0100 Subject: [PATCH 08/22] Feature: faster theme search with indexing by lunr --- package-lock.json | 15 ++ package.json | 1 + scripts/generateLayerOverview.ts | 96 ++++++------- src/Logic/Search/ThemeSearch.ts | 229 +++++++++++++++---------------- src/Logic/State/SearchState.ts | 6 +- src/UI/AllThemesGui.svelte | 31 ++--- 6 files changed, 194 insertions(+), 184 deletions(-) diff --git a/package-lock.json b/package-lock.json index ee7c5bddb72..039afe98e59 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 87869a2070d..5be1d84e885 100644 --- a/package.json +++ b/package.json @@ -208,6 +208,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/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index fb727f7d0c3..1b76b52233d 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/Search/ThemeSearch.ts b/src/Logic/Search/ThemeSearch.ts index 13f8d3e5101..b1b6585b2c8 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 = 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/SearchState.ts b/src/Logic/State/SearchState.ts index 1d017379572..e4bf83bba1c 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/UI/AllThemesGui.svelte b/src/UI/AllThemesGui.svelte index ca745216b1e..c9bed2eaa44 100644 --- a/src/UI/AllThemesGui.svelte +++ b/src/UI/AllThemesGui.svelte @@ -18,15 +18,15 @@ 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({ @@ -65,29 +65,26 @@ 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] ) } From 4db2c86c0ffebc23084f2974d9328b51b80eadbd Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 16 Feb 2025 00:04:48 +0100 Subject: [PATCH 09/22] Feature: add "recently visited themes" on index page --- langs/en.json | 1 + public/css/index-tailwind-output.css | 12 ++++++++---- src/UI/AllThemesGui.svelte | 19 ++++++++++++++++-- src/UI/BigComponents/ThemeButton.svelte | 26 ++++++++++++++----------- src/UI/BigComponents/ThemesList.svelte | 10 ++++++---- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/langs/en.json b/langs/en.json index 83b1916f783..1372e1ae2b4 100644 --- a/langs/en.json +++ b/langs/en.json @@ -616,6 +616,7 @@ "intro": "Maps about various topics which you can contribute to", "learnMore": "Learn more", "logIn": "Log in to see other themes you previously visited", + "recentThemes": "Recently visited themes", "title": "MapComplete" }, "inspector": { diff --git a/public/css/index-tailwind-output.css b/public/css/index-tailwind-output.css index 0df60cd4cf4..908fd6ac44e 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/src/UI/AllThemesGui.svelte b/src/UI/AllThemesGui.svelte index c9bed2eaa44..aad6262cc5c 100644 --- a/src/UI/AllThemesGui.svelte +++ b/src/UI/AllThemesGui.svelte @@ -27,6 +27,7 @@ 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,6 +67,7 @@ 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) @@ -97,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() @@ -162,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 @@ ) - - - - - - - - - +{#if iconOnly} + + + +{:else} + + + + + + + + +{/if} diff --git a/src/UI/BigComponents/ThemesList.svelte b/src/UI/BigComponents/ThemesList.svelte index 3cf0247ccf0..755fa703089 100644 --- a/src/UI/BigComponents/ThemesList.svelte +++ b/src/UI/BigComponents/ThemesList.svelte @@ -7,19 +7,21 @@ import { MinimalThemeInformation } from "../../Models/ThemeConfig/ThemeConfig" import Translations from "../i18n/Translations" import Tr from "../Base/Tr.svelte" + import { twMerge } from "tailwind-merge" - export let search: UIEventSource + export let search: UIEventSource = new UIEventSource(undefined) export let themes: MinimalThemeInformation[] export let state: { osmConnection: OsmConnection } - + export let onlyIcons: boolean = false export let hasSelection: boolean = true
-
+
{#each themes as theme (theme.id)} - + {#if $search && hasSelection && themes?.[0] === theme}