diff --git a/assets/layers/atm/atm.json b/assets/layers/atm/atm.json index 9d247dea0f..e873ec3b2c 100644 --- a/assets/layers/atm/atm.json +++ b/assets/layers/atm/atm.json @@ -581,25 +581,25 @@ "pt": "Em que línguas este multibanco tem saída de fala?" }, "render_list_item": { - "en": "This ATM has speech output in {language():font-bold}", - "de": "Dieser Geldautomat hat eine Sprachausgabe in {language():font-bold}", - "nl": "Deze geldautomaat heeft spraak in {language():font-bold}", - "ca": "Aquest caixer té sortida de veu en {language():font-bold}", - "cs": "Tento bankomat má řečový výstup v {language():font-bold}", - "he": "לכספומט הזה יש פלט דיבור ב {language():font-bold}", - "pt_BR": "Este caixa eletrônico tem saída de fala em {language():font-bold}", - "es": "Este cajero automático tiene salida de voz en {language():font-bold}", - "pt": "Este multibanco tem saída de fala em {language():font-bold}" + "en": "This ATM has speech output in {language()}", + "de": "Dieser Geldautomat hat eine Sprachausgabe in {language()}", + "nl": "Deze geldautomaat heeft spraak in {language()}", + "ca": "Aquest caixer té sortida de veu en {language()}", + "cs": "Tento bankomat má řečový výstup v {language()}", + "he": "לכספומט הזה יש פלט דיבור ב {language()}", + "pt_BR": "Este caixa eletrônico tem saída de fala em {language()}", + "es": "Este cajero automático tiene salida de voz en {language()}", + "pt": "Este multibanco tem saída de fala em {language()}" }, "render_single_language": { - "en": "This ATM has speech output in {language():font-bold}", - "de": "Dieser Geldautomat hat eine Sprachausgabe in {language():font-bold}", - "nl": "Deze automaat heeft spraak in {language():font-bold}", - "ca": "Aquest caixer té sortida de veu en {language():font-bold}", - "cs": "Tento bankomat má řečový výstup v {language():font-bold}", - "he": "לכספומט הזה יש פלט דיבור ב {language():font-bold}", - "pt_BR": "Este caixa eletrônico tem saída de fala em {language():font-bold}", - "es": "Este cajero automático tiene salida de voz en {language():font-bold}" + "en": "This ATM has speech output in {language()}", + "de": "Dieser Geldautomat hat eine Sprachausgabe in {language()}", + "nl": "Deze automaat heeft spraak in {language()}", + "ca": "Aquest caixer té sortida de veu en {language()}", + "cs": "Tento bankomat má řečový výstup v {language()}", + "he": "לכספומט הזה יש פלט דיבור ב {language()}", + "pt_BR": "Este caixa eletrônico tem saída de fala em {language()}", + "es": "Este cajero automático tiene salida de voz en {language()}" } } } diff --git a/assets/layers/elevator/elevator.json b/assets/layers/elevator/elevator.json index a6ad920151..6d4fa23178 100644 --- a/assets/layers/elevator/elevator.json +++ b/assets/layers/elevator/elevator.json @@ -267,18 +267,18 @@ "cs": "Ve kterých jazycích má tento výtah hmatové písmo (braillovo písmo)?" }, "render_list_item": { - "en": "This elevator has tactile writing in {language():font-bold}", - "de": "Der Aufzug hat taktile Schrift in {language():font-bold}", - "nl": "Deze lift heeft voelbaar schrift in het {language():font-bold}", - "ca": "Aquest ascensor té l'escriptura tàctil en {language():font-bold}", - "cs": "Tento výtah má hmatové písmo v {language():font-bold}" + "en": "This elevator has tactile writing in {language()}", + "de": "Der Aufzug hat taktile Schrift in {language()}", + "nl": "Deze lift heeft voelbaar schrift in het {language()}", + "ca": "Aquest ascensor té l'escriptura tàctil en {language()}", + "cs": "Tento výtah má hmatové písmo v {language()}" }, "render_single_language": { - "en": "This elevator has tactile writing in {language():font-bold}", - "de": "Der Aufzug hat taktile Schrift in {language():font-bold}", - "nl": "Deze lift heeft voelbaar schrift in het {language():font-bold}", - "ca": "Aquest ascensor té l'escriptura tàctil en {language():font-bold}", - "cs": "Tento výtah má hmatové písmo v {language():font-bold}" + "en": "This elevator has tactile writing in {language()}", + "de": "Der Aufzug hat taktile Schrift in {language()}", + "nl": "Deze lift heeft voelbaar schrift in het {language()}", + "ca": "Aquest ascensor té l'escriptura tàctil en {language()}", + "cs": "Tento výtah má hmatové písmo v {language()}" } } } @@ -330,18 +330,18 @@ "cs": "Ve kterých jazycích má tento výtah hlasový výstup?" }, "render_list_item": { - "en": "This elevator has speech output in {language():font-bold}", - "nl": "Deze lift heeft gesproken tekst in het {language():font-bold}", - "de": "Der Aufzug hat eine Sprachausgabe in {language():font-bold}", - "ca": "Aquest ascensor té sortida de veu en {language():font-bold}", - "cs": "Tento výtah má hlasový výstup v {language():font-bold}" + "en": "This elevator has speech output in {language()}", + "nl": "Deze lift heeft gesproken tekst in het {language()}", + "de": "Der Aufzug hat eine Sprachausgabe in {language()}", + "ca": "Aquest ascensor té sortida de veu en {language()}", + "cs": "Tento výtah má hlasový výstup v {language()}" }, "render_single_language": { - "en": "This elevator has speech output in {language():font-bold}", - "nl": "Deze lift heeft gesproken tekst in het {language():font-bold}", - "de": "Der Aufzug hat eine Sprachausgabe in {language():font-bold}", - "ca": "Aquest ascensor té sortida de veu en {language():font-bold}", - "cs": "Tento výtah má hlasový výstup v {language():font-bold}" + "en": "This elevator has speech output in {language()}", + "nl": "Deze lift heeft gesproken tekst in het {language()}", + "de": "Der Aufzug hat eine Sprachausgabe in {language()}", + "ca": "Aquest ascensor té sortida de veu en {language()}", + "cs": "Tento výtah má hlasový výstup v {language()}" } } } diff --git a/assets/layers/school/school.json b/assets/layers/school/school.json index c8d26be0ec..07ef243ced 100644 --- a/assets/layers/school/school.json +++ b/assets/layers/school/school.json @@ -435,12 +435,12 @@ "cs": "V této škole se používají následující jazyky:{list()}" }, "render_single_language": { - "en": "{language():font-bold} is the main language of this school", - "de": "{language():font-bold} ist die Hauptsprache der Schule", - "ca": "{language():font-bold} és la llengua principal d'aquesta escola", - "fr": "{language():font-bold} est la langue principale dans cette école", - "pl": "Język {language():font-bold} jest głównym językiem używanym w tej szkole", - "cs": "{language():font-bold} je hlavním jazykem této školy" + "en": "{language()} is the main language of this school", + "de": "{language()} ist die Hauptsprache der Schule", + "ca": "{language()} és la llengua principal d'aquesta escola", + "fr": "{language()} est la langue principale dans cette école", + "pl": "Język {language()} jest głównym językiem używanym w tej szkole", + "cs": "{language()} je hlavním jazykem této školy" }, "question": { "en": "What is the main language of this school?
What language is spoken with the students in non-language related courses and with the administration?
", diff --git a/assets/layers/stairs/stairs.json b/assets/layers/stairs/stairs.json index 8e55fe971c..c51fbf6a50 100644 --- a/assets/layers/stairs/stairs.json +++ b/assets/layers/stairs/stairs.json @@ -205,18 +205,18 @@ "cs": "Ve kterých jazycích existuje hmatové písmo (braillské písmo) pro navigaci? " }, "render_list_item": { - "en": "These stairs have tactile writing in {language():font-bold}", - "de": "Die Treppe hat taktile Schrift in {language():font-bold}", - "nl": "Deze trap heeft voelbaar schrijft in {language():font-bold}", - "ca": "Aquestes escales tenen escriptura tàctil en {language():font-bold}", - "cs": "Tyto schody mají hmatové písmo v {language():font-bold}" + "en": "These stairs have tactile writing in {language()}", + "de": "Die Treppe hat taktile Schrift in {language()}", + "nl": "Deze trap heeft voelbaar schrijft in {language()}", + "ca": "Aquestes escales tenen escriptura tàctil en {language()}", + "cs": "Tyto schody mají hmatové písmo v {language()}" }, "render_single_language": { - "en": "These stairs have tactile writing in {language():font-bold}", - "de": "Die Treppe hat taktile Schrift in {language():font-bold}", - "nl": "Deze trap heeft voelbaar schrijft in {language():font-bold}", - "ca": "Aquestes escales tenen escriptura tàctil en {language():font-bold}", - "cs": "Tyto schody mají hmatové písmo v {language():font-bold}" + "en": "These stairs have tactile writing in {language()}", + "de": "Die Treppe hat taktile Schrift in {language()}", + "nl": "Deze trap heeft voelbaar schrijft in {language()}", + "ca": "Aquestes escales tenen escriptura tàctil en {language()}", + "cs": "Tyto schody mají hmatové písmo v {language()}" } } } diff --git a/langs/layers/ca.json b/langs/layers/ca.json index 4653df83b9..015d90e7a6 100644 --- a/langs/layers/ca.json +++ b/langs/layers/ca.json @@ -35,16 +35,6 @@ "1": { "title": "un mupi" }, - "10": { - "description": "S'utilitza per a cartells publicitaris, rètols de neó, logotips i cartells en entrades institucionals", - "title": "un lletrer" - }, - "11": { - "title": "una escupltura" - }, - "12": { - "title": "una paret pintada" - }, "2": { "title": "un mupi sobre la paret" }, @@ -71,6 +61,16 @@ }, "9": { "title": "un tòtem" + }, + "10": { + "description": "S'utilitza per a cartells publicitaris, rètols de neó, logotips i cartells en entrades institucionals", + "title": "un lletrer" + }, + "11": { + "title": "una escupltura" + }, + "12": { + "title": "una paret pintada" } }, "tagRenderings": { @@ -165,9 +165,6 @@ "1": { "then": "Açò és un tauló d'anunis" }, - "10": { - "then": "Açò és una paret pintada" - }, "2": { "then": "Açò és una columna" }, @@ -191,6 +188,9 @@ }, "9": { "then": "Açò és un tòtem" + }, + "10": { + "then": "Açò és una paret pintada" } }, "question": "Quin tipus d'element publicitari és aquest?", @@ -205,9 +205,6 @@ "1": { "then": "Tauló d'anuncis" }, - "10": { - "then": "Paret Pintada" - }, "2": { "then": "Mupi" }, @@ -231,6 +228,9 @@ }, "9": { "then": "Tòtem" + }, + "10": { + "then": "Paret Pintada" } } } @@ -351,15 +351,6 @@ "1": { "then": "Mural" }, - "10": { - "then": "Azulejo (Rajoles decoratives espanyoles i portugueses)" - }, - "11": { - "then": "Enrajolat" - }, - "12": { - "then": "Tallat a la fusta" - }, "2": { "then": "Pintura" }, @@ -383,6 +374,15 @@ }, "9": { "then": "Relleu" + }, + "10": { + "then": "Azulejo (Rajoles decoratives espanyoles i portugueses)" + }, + "11": { + "then": "Enrajolat" + }, + "12": { + "then": "Tallat a la fusta" } }, "question": "Quin tipus d'obra és aquesta peça?", @@ -528,8 +528,8 @@ "render": { "special": { "question": "En quins idiomes té sortida de veu aquest caixer?", - "render_list_item": "Aquest caixer té sortida de veu en {language():font-bold}", - "render_single_language": "Aquest caixer té sortida de veu en {language():font-bold}" + "render_list_item": "Aquest caixer té sortida de veu en {language()}", + "render_single_language": "Aquest caixer té sortida de veu en {language()}" } } } @@ -1920,30 +1920,6 @@ "1": { "then": "Endoll de paret Schuko sense pin a terra (CEE7/4 tipus F)" }, - "10": { - "then": "CSS Tipus 1 (també conegut com a Tipus 1 Combo)" - }, - "11": { - "then": "CSS Tipus 1 (també conegut com a Tipus 1 Combo)" - }, - "12": { - "then": "Supercarregador de Tesla" - }, - "13": { - "then": "Supercarregador de Tesla" - }, - "14": { - "then": "Tipus 2 (mennekes)" - }, - "15": { - "then": "Tipus 2 (mennekes)" - }, - "16": { - "then": "CSS Tipus 2 (mennekes)" - }, - "17": { - "then": "CSS Tipus 2 (mennekes)" - }, "2": { "then": "Endoll de paret Europeu amb pin a terra (CEE7/4 tipus E)" }, @@ -1967,6 +1943,30 @@ }, "9": { "then": "Tipus 1 sense cable(J1772)" + }, + "10": { + "then": "CSS Tipus 1 (també conegut com a Tipus 1 Combo)" + }, + "11": { + "then": "CSS Tipus 1 (també conegut com a Tipus 1 Combo)" + }, + "12": { + "then": "Supercarregador de Tesla" + }, + "13": { + "then": "Supercarregador de Tesla" + }, + "14": { + "then": "Tipus 2 (mennekes)" + }, + "15": { + "then": "Tipus 2 (mennekes)" + }, + "16": { + "then": "CSS Tipus 2 (mennekes)" + }, + "17": { + "then": "CSS Tipus 2 (mennekes)" } } }, @@ -2112,13 +2112,6 @@ } } } - }, - "title": { - "mappings": { - "1": { - "then": "Estació de càrrega per a cotxes" - } - } } }, "climbing": { @@ -2643,9 +2636,6 @@ "1": { "then": "Aquesta via ciclista està pavimentada" }, - "10": { - "then": "Aquesta via ciclista està feta de grava fina" - }, "2": { "then": "Aquesta via ciclista està feta d'asfalt" }, @@ -2669,6 +2659,9 @@ }, "9": { "then": "Aquesta via ciclista està feta de grava" + }, + "10": { + "then": "Aquesta via ciclista està feta de grava fina" } }, "question": "De quina superfície està fet aquesta via ciclista?", @@ -2714,9 +2707,6 @@ "1": { "then": "Aquest carril bici està pavimentat" }, - "10": { - "then": "Aquesta via ciclista està feta de gravilla" - }, "2": { "then": "Aquest carril bici està fet d'asfalt" }, @@ -2728,6 +2718,9 @@ }, "9": { "then": "Aquesta via ciclista està feta de grava" + }, + "10": { + "then": "Aquesta via ciclista està feta de gravilla" } }, "question": "De què està feta la superfície d'aquest carrer?", @@ -3227,8 +3220,8 @@ "render": { "special": { "question": "Aquest ascensor en quins idiomes té sortida de veu?", - "render_list_item": "Aquest ascensor té sortida de veu en {language():font-bold}", - "render_single_language": "Aquest ascensor té sortida de veu en {language():font-bold}" + "render_list_item": "Aquest ascensor té sortida de veu en {language()}", + "render_single_language": "Aquest ascensor té sortida de veu en {language()}" } } }, @@ -3250,8 +3243,8 @@ "render": { "special": { "question": "Aquest ascensor en quins idiomes té l'escriptura tàctil (braille)?", - "render_list_item": "Aquest ascensor té l'escriptura tàctil en {language():font-bold}", - "render_single_language": "Aquest ascensor té l'escriptura tàctil en {language():font-bold}" + "render_list_item": "Aquest ascensor té l'escriptura tàctil en {language()}", + "render_single_language": "Aquest ascensor té l'escriptura tàctil en {language()}" } } } @@ -3746,21 +3739,6 @@ "1": { "then": "Aquesta estació de fitness té un cartell amb instruccions per a un exercici concret." }, - "10": { - "then": "Aquesta estació de gimnàs té esglaons." - }, - "11": { - "then": "Aquesta estació de fitness disposa de cons per fer salts de granota." - }, - "12": { - "then": "Aquesta estació de fitness té bigues per saltar." - }, - "13": { - "then": "Aquesta estació de fitness té obstacles per a travesar." - }, - "14": { - "then": "Aquesta estació de fitness té una paret per enfilar-se." - }, "2": { "then": "Aquesta estació de fitness té una instal·lació per fer abdominals." }, @@ -3784,6 +3762,21 @@ }, "9": { "then": "Aquesta estació de fitness té llocs per fer exercicis d'eslàlom." + }, + "10": { + "then": "Aquesta estació de gimnàs té esglaons." + }, + "11": { + "then": "Aquesta estació de fitness disposa de cons per fer salts de granota." + }, + "12": { + "then": "Aquesta estació de fitness té bigues per saltar." + }, + "13": { + "then": "Aquesta estació de fitness té obstacles per a travesar." + }, + "14": { + "then": "Aquesta estació de fitness té una paret per enfilar-se." } } } @@ -3902,21 +3895,6 @@ "1": { "then": "Això és una fregiduria" }, - "10": { - "then": "Aquí es serveixen plats xinesos" - }, - "11": { - "then": "Aquí es serveixen plats grecs" - }, - "12": { - "then": "Aquí es serveixen plats indis" - }, - "13": { - "then": "Aquí es serveixen plats turcs" - }, - "14": { - "then": "Aquí es serveixen plats tailandesos" - }, "2": { "then": "Principalment serveix pasta" }, @@ -3940,6 +3918,21 @@ }, "9": { "then": "Aquí es serveixen plats francesos" + }, + "10": { + "then": "Aquí es serveixen plats xinesos" + }, + "11": { + "then": "Aquí es serveixen plats grecs" + }, + "12": { + "then": "Aquí es serveixen plats indis" + }, + "13": { + "then": "Aquí es serveixen plats turcs" + }, + "14": { + "then": "Aquí es serveixen plats tailandesos" } }, "question": "Quin tipus de menjar es serveix aquí?", @@ -4492,24 +4485,9 @@ "1": { "then": "Açò és un auditori" }, - "10": { - "then": "Açò és un laboratori" - }, - "14": { - "then": "Açò és una oficina" - }, - "16": { - "then": "Açò és un restaurant" - }, - "19": { - "then": "Açò és un magatzem" - }, "2": { "then": "Açò és un dormitori" }, - "22": { - "then": "Açò és una sala d'espera" - }, "3": { "then": "Açò és una capella" }, @@ -4527,6 +4505,21 @@ }, "9": { "then": "Açò és una cuina" + }, + "10": { + "then": "Açò és un laboratori" + }, + "14": { + "then": "Açò és una oficina" + }, + "16": { + "then": "Açò és un restaurant" + }, + "19": { + "then": "Açò és un magatzem" + }, + "22": { + "then": "Açò és una sala d'espera" } }, "question": "Quin tipus d'habitació és aquesta?" @@ -5128,19 +5121,6 @@ } } }, - "10": { - "options": { - "0": { - "question": "Totes les notes" - }, - "1": { - "question": "Oculta les notes d'importació" - }, - "2": { - "question": "Mostrar només les notes d'importació" - } - } - }, "2": { "options": { "0": { @@ -5196,6 +5176,19 @@ "question": "Sols mostra les notes obertes" } } + }, + "10": { + "options": { + "0": { + "question": "Totes les notes" + }, + "1": { + "question": "Oculta les notes d'importació" + }, + "2": { + "question": "Mostrar només les notes d'importació" + } + } } }, "name": "Notes d'OpenStreetMap", @@ -5495,15 +5488,6 @@ "1": { "then": "Aquesta és una plaça d'aparcament normal." }, - "10": { - "then": "Es tracta d'una plaça d'aparcament reservada per a pares amb fills." - }, - "11": { - "then": "Es tracta d'una plaça d'aparcament reservada al personal." - }, - "12": { - "then": "Aquest espai d'aparcament està reservat per a taxi." - }, "2": { "then": "Aquesta és una plaça d'aparcament per a minusvàlids." }, @@ -5521,6 +5505,15 @@ }, "9": { "then": "Es tracta d'una plaça d'aparcament reservada per a motos." + }, + "10": { + "then": "Es tracta d'una plaça d'aparcament reservada per a pares amb fills." + }, + "11": { + "then": "Es tracta d'una plaça d'aparcament reservada al personal." + }, + "12": { + "then": "Aquest espai d'aparcament està reservat per a taxi." } }, "question": "Quin tipus d'espai d'aparcament és aquest?" @@ -6095,21 +6088,6 @@ "1": { "then": "S'accepten monedes de 2 cèntims" }, - "10": { - "then": "S'accepten monedes de 20 cèntims" - }, - "11": { - "then": "S'accepten monedes de ½ franc" - }, - "12": { - "then": "S'accepten monedes d'1 franc" - }, - "13": { - "then": "S'accepten monedes de 2 francs" - }, - "14": { - "then": "S'accepten monedes de 5 francs" - }, "2": { "then": "S'accepten monedes de 5 cèntims" }, @@ -6133,6 +6111,21 @@ }, "9": { "then": "S'accepten monedes de 10 cèntims" + }, + "10": { + "then": "S'accepten monedes de 20 cèntims" + }, + "11": { + "then": "S'accepten monedes de ½ franc" + }, + "12": { + "then": "S'accepten monedes d'1 franc" + }, + "13": { + "then": "S'accepten monedes de 2 francs" + }, + "14": { + "then": "S'accepten monedes de 5 francs" } }, "question": "Quines monedes es poden utilitzar per a pagar aquí?" @@ -6145,15 +6138,6 @@ "1": { "then": "S'accepten bitllets de 10 euros" }, - "10": { - "then": "S'accepten bitllets de 100 francs" - }, - "11": { - "then": "S'accepten bitllets de 200 francs" - }, - "12": { - "then": "S'accepten bitllets de 1000 francs" - }, "2": { "then": "S'accepten bitllets de 20 euros" }, @@ -6177,6 +6161,15 @@ }, "9": { "then": "S'accepten bitllets de 50 francs" + }, + "10": { + "then": "S'accepten bitllets de 100 francs" + }, + "11": { + "then": "S'accepten bitllets de 200 francs" + }, + "12": { + "then": "S'accepten bitllets de 1000 francs" } }, "question": "Amb quins bitllets pot pagar aquí?" @@ -6531,6 +6524,30 @@ "1": { "question": "Reciclatge de piles" }, + "2": { + "question": "Reciclatge de cartrons de begudes" + }, + "3": { + "question": "Reciclatge de llaunes" + }, + "4": { + "question": "Reciclatge de roba" + }, + "5": { + "question": "Reciclatge d'oli de cuina" + }, + "6": { + "question": "Reciclatge d'oli de motor" + }, + "7": { + "question": "Reciclatge de tubs fluorescents" + }, + "8": { + "question": "Reciclatge de residus verds" + }, + "9": { + "question": "Reciclatge d'ampolles de vidre" + }, "10": { "question": "Reciclatge de vidre" }, @@ -6561,35 +6578,11 @@ "19": { "question": "Reciclatge del rebuig" }, - "2": { - "question": "Reciclatge de cartrons de begudes" - }, "20": { "question": "Reciclatge de cartutxos d'impressora" }, "21": { "question": "Reciclatge de bicicletes" - }, - "3": { - "question": "Reciclatge de llaunes" - }, - "4": { - "question": "Reciclatge de roba" - }, - "5": { - "question": "Reciclatge d'oli de cuina" - }, - "6": { - "question": "Reciclatge d'oli de motor" - }, - "7": { - "question": "Reciclatge de tubs fluorescents" - }, - "8": { - "question": "Reciclatge de residus verds" - }, - "9": { - "question": "Reciclatge d'ampolles de vidre" } } }, @@ -6657,6 +6650,30 @@ "1": { "then": "Aquí es poden reciclar els cartons de begudes" }, + "2": { + "then": "Aquí es poden reciclar llaunes" + }, + "3": { + "then": "Aquí es pot reciclar roba" + }, + "4": { + "then": "Aquí es pot reciclar oli de cuina" + }, + "5": { + "then": "Aquí es pot reciclar oli de motor" + }, + "6": { + "then": "Aquí es poden reciclar tub fluroescents" + }, + "7": { + "then": "Aquí es poden reciclar residus verds" + }, + "8": { + "then": "Ací es poden reciclar residus orgànics" + }, + "9": { + "then": "Aquí es poden reciclar ampolles de vidre" + }, "10": { "then": "Aquí es pot reciclar vidre" }, @@ -6687,9 +6704,6 @@ "19": { "then": "Aquí es poden reciclar sabates" }, - "2": { - "then": "Aquí es poden reciclar llaunes" - }, "20": { "then": "Aquí es poden reciclar petits electrodomèstics" }, @@ -6704,27 +6718,6 @@ }, "24": { "then": "Aquí es poden reciclar bicicletes" - }, - "3": { - "then": "Aquí es pot reciclar roba" - }, - "4": { - "then": "Aquí es pot reciclar oli de cuina" - }, - "5": { - "then": "Aquí es pot reciclar oli de motor" - }, - "6": { - "then": "Aquí es poden reciclar tub fluroescents" - }, - "7": { - "then": "Aquí es poden reciclar residus verds" - }, - "8": { - "then": "Ací es poden reciclar residus orgànics" - }, - "9": { - "then": "Aquí es poden reciclar ampolles de vidre" } }, "question": "Què es pot reciclar aquí?" @@ -6835,7 +6828,7 @@ "no_known_languages": "La llengua principal d'aquesta escola és desconeguda", "question": "Quina és la llengua principal d'aquesta escola?
Quina llengua es parla amb els estudiants en classes no relacionades amb la llengua i l'administració?
", "render_all": "En aquesta escola s'utilitzen els idiomes següents:{list()}", - "render_single_language": "{language():font-bold} és la llengua principal d'aquesta escola" + "render_single_language": "{language()} és la llengua principal d'aquesta escola" } } }, @@ -7381,8 +7374,8 @@ "render": { "special": { "question": "En quins idiomes hi ha escriptura tàctil (braille) per a la navegació? ", - "render_list_item": "Aquestes escales tenen escriptura tàctil en {language():font-bold}", - "render_single_language": "Aquestes escales tenen escriptura tàctil en {language():font-bold}" + "render_list_item": "Aquestes escales tenen escriptura tàctil en {language()}", + "render_single_language": "Aquestes escales tenen escriptura tàctil en {language()}" } } } @@ -7472,12 +7465,6 @@ "1": { "then": "Aquest fanal utilitza LED" }, - "10": { - "then": "Aquest fanal utilitza làmpades de sodi d'alta pressió (taronja amb blanc)" - }, - "11": { - "then": "Aquest fanal s'il·lumina amb gas" - }, "2": { "then": "Aquest fanal utilitza il·luminació incandescent" }, @@ -7501,6 +7488,12 @@ }, "9": { "then": "Aquest fanal utilitza làmpades de sodi de baixa pressió (taronja monocroma)" + }, + "10": { + "then": "Aquest fanal utilitza làmpades de sodi d'alta pressió (taronja amb blanc)" + }, + "11": { + "then": "Aquest fanal s'il·lumina amb gas" } }, "question": "Quin tipus d'il·luminació utilitza aquest fanal?" @@ -8705,6 +8698,30 @@ "1": { "question": "Venda de begudes" }, + "2": { + "question": "Venda de llaminadures" + }, + "3": { + "question": "Venda de menjar" + }, + "4": { + "question": "Venda de tabaco" + }, + "5": { + "question": "Venda de preservatius" + }, + "6": { + "question": "Venda de cafè" + }, + "7": { + "question": "Venda d'aigua" + }, + "8": { + "question": "Venda de diaris" + }, + "9": { + "question": "Venda de càmeres interiors de bicicletes" + }, "10": { "question": "Venda de llet" }, @@ -8735,9 +8752,6 @@ "19": { "question": "Venda de flors" }, - "2": { - "question": "Venda de llaminadures" - }, "20": { "question": "Venda de tiquets d'aparcament" }, @@ -8761,27 +8775,6 @@ }, "27": { "question": "Venda de cadenat per a bicicletes" - }, - "3": { - "question": "Venda de menjar" - }, - "4": { - "question": "Venda de tabaco" - }, - "5": { - "question": "Venda de preservatius" - }, - "6": { - "question": "Venda de cafè" - }, - "7": { - "question": "Venda d'aigua" - }, - "8": { - "question": "Venda de diaris" - }, - "9": { - "question": "Venda de càmeres interiors de bicicletes" } } } @@ -8828,6 +8821,30 @@ "1": { "then": "Es venen llaminadures" }, + "2": { + "then": "Es ven menjar" + }, + "3": { + "then": "Es ven tabaco" + }, + "4": { + "then": "Es venen preservatius" + }, + "5": { + "then": "Es ven cafè" + }, + "6": { + "then": "Es ven aigua" + }, + "7": { + "then": "Es venen diaris" + }, + "8": { + "then": "Es venen càmeres interiors de bicicletes" + }, + "9": { + "then": "Es ven llet" + }, "10": { "then": "Es ven pa" }, @@ -8858,9 +8875,6 @@ "19": { "then": "Es venen tiquets d'aparcament" }, - "2": { - "then": "Es ven menjar" - }, "20": { "then": "Es venen cèntims premsats" }, @@ -8881,27 +8895,6 @@ }, "26": { "then": "Es venen cadenats per a bicicletes" - }, - "3": { - "then": "Es ven tabaco" - }, - "4": { - "then": "Es venen preservatius" - }, - "5": { - "then": "Es ven cafè" - }, - "6": { - "then": "Es ven aigua" - }, - "7": { - "then": "Es venen diaris" - }, - "8": { - "then": "Es venen càmeres interiors de bicicletes" - }, - "9": { - "then": "Es ven llet" } }, "question": "Que ven aquesta màquina expenedora?", @@ -9193,4 +9186,4 @@ "render": "Turbina eòlica" } } -} +} \ No newline at end of file diff --git a/langs/layers/cs.json b/langs/layers/cs.json index 79561d7cae..8b99ac086f 100644 --- a/langs/layers/cs.json +++ b/langs/layers/cs.json @@ -489,8 +489,8 @@ "render": { "special": { "question": "V jakých jazycích má tento bankomat řečový výstup?", - "render_list_item": "Tento bankomat má řečový výstup v {language():font-bold}", - "render_single_language": "Tento bankomat má řečový výstup v {language():font-bold}" + "render_list_item": "Tento bankomat má řečový výstup v {language()}", + "render_single_language": "Tento bankomat má řečový výstup v {language()}" } } } @@ -3269,8 +3269,8 @@ "render": { "special": { "question": "Ve kterých jazycích má tento výtah hlasový výstup?", - "render_list_item": "Tento výtah má hlasový výstup v {language():font-bold}", - "render_single_language": "Tento výtah má hlasový výstup v {language():font-bold}" + "render_list_item": "Tento výtah má hlasový výstup v {language()}", + "render_single_language": "Tento výtah má hlasový výstup v {language()}" } } }, @@ -3301,8 +3301,8 @@ "render": { "special": { "question": "Ve kterých jazycích má tento výtah hmatové písmo (braillovo písmo)?", - "render_list_item": "Tento výtah má hmatové písmo v {language():font-bold}", - "render_single_language": "Tento výtah má hmatové písmo v {language():font-bold}" + "render_list_item": "Tento výtah má hmatové písmo v {language()}", + "render_single_language": "Tento výtah má hmatové písmo v {language()}" } } } @@ -7113,7 +7113,7 @@ "no_known_languages": "Hlavní jazyk této školy není znám", "question": "Jaký je hlavní jazyk této školy?
Jakým jazykem se mluví se studenty v nejazykových kurzech a administrativou?
", "render_all": "V této škole se používají následující jazyky:{list()}", - "render_single_language": "{language():font-bold} je hlavním jazykem této školy" + "render_single_language": "{language()} je hlavním jazykem této školy" } } }, @@ -7699,8 +7699,8 @@ "render": { "special": { "question": "Ve kterých jazycích existuje hmatové písmo (braillské písmo) pro navigaci? ", - "render_list_item": "Tyto schody mají hmatové písmo v {language():font-bold}", - "render_single_language": "Tyto schody mají hmatové písmo v {language():font-bold}" + "render_list_item": "Tyto schody mají hmatové písmo v {language()}", + "render_single_language": "Tyto schody mají hmatové písmo v {language()}" } } } diff --git a/langs/layers/de.json b/langs/layers/de.json index d5cb439c84..a74db0403d 100644 --- a/langs/layers/de.json +++ b/langs/layers/de.json @@ -530,8 +530,8 @@ "render": { "special": { "question": "In welchen Sprachen hat dieser Geldautomat eine Sprachausgabe?", - "render_list_item": "Dieser Geldautomat hat eine Sprachausgabe in {language():font-bold}", - "render_single_language": "Dieser Geldautomat hat eine Sprachausgabe in {language():font-bold}" + "render_list_item": "Dieser Geldautomat hat eine Sprachausgabe in {language()}", + "render_single_language": "Dieser Geldautomat hat eine Sprachausgabe in {language()}" } } } @@ -3859,8 +3859,8 @@ "render": { "special": { "question": "In welchen Sprachen verfügt der Aufzug über eine Sprachausgabe?", - "render_list_item": "Der Aufzug hat eine Sprachausgabe in {language():font-bold}", - "render_single_language": "Der Aufzug hat eine Sprachausgabe in {language():font-bold}" + "render_list_item": "Der Aufzug hat eine Sprachausgabe in {language()}", + "render_single_language": "Der Aufzug hat eine Sprachausgabe in {language()}" } } }, @@ -3891,8 +3891,8 @@ "render": { "special": { "question": "In welchen Sprachen hat der Aufzug taktile Schrift (Braille)?", - "render_list_item": "Der Aufzug hat taktile Schrift in {language():font-bold}", - "render_single_language": "Der Aufzug hat taktile Schrift in {language():font-bold}" + "render_list_item": "Der Aufzug hat taktile Schrift in {language()}", + "render_single_language": "Der Aufzug hat taktile Schrift in {language()}" } } } @@ -7949,7 +7949,7 @@ "no_known_languages": "Die Unterrichtssprache der Schule ist unbekannt", "question": "Was ist die Hauptsprache dieser Schule?
Welche Sprache wird mit den Schülern in den nicht sprachbezogenen Kursen und mit der Verwaltung gesprochen?
", "render_all": "Folgende Sprachen werden in der Schule verwendet:{list()}", - "render_single_language": "{language():font-bold} ist die Hauptsprache der Schule" + "render_single_language": "{language()} ist die Hauptsprache der Schule" } } }, @@ -8620,8 +8620,8 @@ "render": { "special": { "question": "In welchen Sprachen gibt es taktile Schrift (Braille) für die Navigation? ", - "render_list_item": "Die Treppe hat taktile Schrift in {language():font-bold}", - "render_single_language": "Die Treppe hat taktile Schrift in {language():font-bold}" + "render_list_item": "Die Treppe hat taktile Schrift in {language()}", + "render_single_language": "Die Treppe hat taktile Schrift in {language()}" } } } diff --git a/langs/layers/en.json b/langs/layers/en.json index 250ee88dbe..58b29662f5 100644 --- a/langs/layers/en.json +++ b/langs/layers/en.json @@ -530,8 +530,8 @@ "render": { "special": { "question": "In which languages does this ATM have speech output?", - "render_list_item": "This ATM has speech output in {language():font-bold}", - "render_single_language": "This ATM has speech output in {language():font-bold}" + "render_list_item": "This ATM has speech output in {language()}", + "render_single_language": "This ATM has speech output in {language()}" } } } @@ -1809,6 +1809,24 @@ "render": "Bird watching place" } }, + "brothel": { + "description": "An establishment specifically dedicated to prostitution. ", + "name": "Brothels", + "presets": { + "0": { + "title": "a brothel" + } + }, + "tagRenderings": { + "name": { + "question": "What is the name of this brothel?", + "render": "This brothel is named {name}" + } + }, + "title": { + "render": "Brothel" + } + }, "cafe_pub": { "deletion": { "extraDeleteReasons": { @@ -2385,6 +2403,26 @@ "render": "Charging station" } }, + "cinema": { + "description": " A place showing movies (films), generally open to the public for a fee. Commonly referred to as a movie theater in the US", + "name": "Cinema", + "tagRenderings": { + "cinema_type": { + "mappings": { + "0": { + "then": "This is a normal cinema showing movies for all ages" + }, + "1": { + "then": "This is an erotic cinema showing adult movies" + } + }, + "question": "What type of cinema is this?" + } + }, + "title": { + "render": "Cinema" + } + }, "climbing": { "description": "A dummy layer which contains tagrenderings, shared among the climbing layers", "tagRenderings": { @@ -3859,8 +3897,8 @@ "render": { "special": { "question": "In which languages does this elevator have speech output?", - "render_list_item": "This elevator has speech output in {language():font-bold}", - "render_single_language": "This elevator has speech output in {language():font-bold}" + "render_list_item": "This elevator has speech output in {language()}", + "render_single_language": "This elevator has speech output in {language()}" } } }, @@ -3891,8 +3929,8 @@ "render": { "special": { "question": "In which languages does this elevator have tactile writing (braille)?", - "render_list_item": "This elevator has tactile writing in {language():font-bold}", - "render_single_language": "This elevator has tactile writing in {language():font-bold}" + "render_list_item": "This elevator has tactile writing in {language()}", + "render_single_language": "This elevator has tactile writing in {language()}" } } } @@ -5024,6 +5062,9 @@ }, "1": { "then": "There is no {negative-name} available at this hackerspace" + }, + "2": { + "then": "There is a limited {negative-name} available at this hackerspace" } }, "question": "Is {device-name} available at this hackerspace?" @@ -5622,6 +5663,25 @@ } } }, + "love_hotel": { + "description": "A love hotel is a type of short-stay hotel found around the world operated primarily for the purpose of allowing guests privacy for sexual activities", + "name": "Love hotels", + "presets": { + "0": { + "description": "A love hotel is a type of short-stay hotel found around the world operated primarily for the purpose of allowing guests privacy for sexual activities.", + "title": "a love hotel" + } + }, + "tagRenderings": { + "name": { + "question": "What is the name of this love hotel?", + "render": "This love hotel is named {name}" + } + }, + "title": { + "render": "Love Hotel {name}" + } + }, "map": { "description": "A map, meant for tourists which is permanently installed in the public space", "name": "Maps", @@ -7949,7 +8009,7 @@ "no_known_languages": "The main language of this school is unknown", "question": "What is the main language of this school?
What language is spoken with the students in non-language related courses and with the administration?
", "render_all": "The following languages are used in this school:{list()}", - "render_single_language": "{language():font-bold} is the main language of this school" + "render_single_language": "{language()} is the main language of this school" } } }, @@ -8620,8 +8680,8 @@ "render": { "special": { "question": "In which languages is there tactile writing (braille) for navigation? ", - "render_list_item": "These stairs have tactile writing in {language():font-bold}", - "render_single_language": "These stairs have tactile writing in {language():font-bold}" + "render_list_item": "These stairs have tactile writing in {language()}", + "render_single_language": "These stairs have tactile writing in {language()}" } } } @@ -8784,6 +8844,24 @@ "render": "Street Lamp" } }, + "stripclub": { + "description": "A venue where erotic dance, striptease, or lap dances are performed commercially. ", + "name": "Stripclubs", + "presets": { + "0": { + "title": "a stripclub" + } + }, + "tagRenderings": { + "name": { + "question": "What is the name of this stripclub?", + "render": "This stripclub is named {name}" + } + }, + "title": { + "render": "Stripclub" + } + }, "surveillance_camera": { "description": "This layer shows surveillance cameras and allows a contributor to update information and add new cameras", "name": "Surveillance camera's", diff --git a/langs/layers/es.json b/langs/layers/es.json index 5d5bc8e368..a5157d619c 100644 --- a/langs/layers/es.json +++ b/langs/layers/es.json @@ -530,8 +530,8 @@ "render": { "special": { "question": "¿En qué idiomas tiene salida de voz este cajero automático?", - "render_list_item": "Este cajero automático tiene salida de voz en {language():font-bold}", - "render_single_language": "Este cajero automático tiene salida de voz en {language():font-bold}" + "render_list_item": "Este cajero automático tiene salida de voz en {language()}", + "render_single_language": "Este cajero automático tiene salida de voz en {language()}" } } } diff --git a/langs/layers/fr.json b/langs/layers/fr.json index d98f26c969..5c2fc8afd3 100644 --- a/langs/layers/fr.json +++ b/langs/layers/fr.json @@ -5232,7 +5232,7 @@ "no_known_languages": "La langue principale de cette école est inconnue", "question": "Quelle est la langue principale de cette école ?
Quelle langue est parlée avec les élèves des cours non linguistiques et avec l'administration ?
", "render_all": "Ces langues sont utilisées dans cette école :{list()}", - "render_single_language": "{language():font-bold} est la langue principale dans cette école" + "render_single_language": "{language()} est la langue principale dans cette école" } } }, diff --git a/langs/layers/he.json b/langs/layers/he.json index 7b9585d41d..9f06b9efab 100644 --- a/langs/layers/he.json +++ b/langs/layers/he.json @@ -281,8 +281,8 @@ "render": { "special": { "question": "באילו שפות יש לכספומט הזה פלט דיבור?", - "render_list_item": "לכספומט הזה יש פלט דיבור ב {language():font-bold}", - "render_single_language": "לכספומט הזה יש פלט דיבור ב {language():font-bold}" + "render_list_item": "לכספומט הזה יש פלט דיבור ב {language()}", + "render_single_language": "לכספומט הזה יש פלט דיבור ב {language()}" } } } diff --git a/langs/layers/nl.json b/langs/layers/nl.json index dbbc87fc18..4ca5d1c69f 100644 --- a/langs/layers/nl.json +++ b/langs/layers/nl.json @@ -385,8 +385,8 @@ "render": { "special": { "question": "In welke taal is de spraak van deze geldautomaat?", - "render_list_item": "Deze geldautomaat heeft spraak in {language():font-bold}", - "render_single_language": "Deze automaat heeft spraak in {language():font-bold}" + "render_list_item": "Deze geldautomaat heeft spraak in {language()}", + "render_single_language": "Deze automaat heeft spraak in {language()}" } } } @@ -3684,8 +3684,8 @@ "render": { "special": { "question": "In welke talen heeft deze lift gesproken tekst?", - "render_list_item": "Deze lift heeft gesproken tekst in het {language():font-bold}", - "render_single_language": "Deze lift heeft gesproken tekst in het {language():font-bold}" + "render_list_item": "Deze lift heeft gesproken tekst in het {language()}", + "render_single_language": "Deze lift heeft gesproken tekst in het {language()}" } } }, @@ -3693,8 +3693,8 @@ "render": { "special": { "question": "In welke talen heeft deze lift voelbaar schrift (braille)?", - "render_list_item": "Deze lift heeft voelbaar schrift in het {language():font-bold}", - "render_single_language": "Deze lift heeft voelbaar schrift in het {language():font-bold}" + "render_list_item": "Deze lift heeft voelbaar schrift in het {language()}", + "render_single_language": "Deze lift heeft voelbaar schrift in het {language()}" } } } @@ -4498,6 +4498,9 @@ }, "1": { "then": "Er is geen {negative-name} beschikbaar in deze hackerspace" + }, + "2": { + "then": "Er is een beperkte {negative-name} beschikbaar in deze hackerspace" } }, "question": "Is er {device-name} beschikbaar in deze hackerspace?" @@ -7533,8 +7536,8 @@ "render": { "special": { "question": "In welke talen is er voelbaar schrift (braille) voor navigatie? ", - "render_list_item": "Deze trap heeft voelbaar schrijft in {language():font-bold}", - "render_single_language": "Deze trap heeft voelbaar schrijft in {language():font-bold}" + "render_list_item": "Deze trap heeft voelbaar schrijft in {language()}", + "render_single_language": "Deze trap heeft voelbaar schrijft in {language()}" } } } diff --git a/langs/layers/pl.json b/langs/layers/pl.json index bc9c9bd820..7b9258b572 100644 --- a/langs/layers/pl.json +++ b/langs/layers/pl.json @@ -2604,7 +2604,7 @@ "render": { "special": { "render_all": "Następujące języki są używane w tej szkole:{list()}", - "render_single_language": "Język {language():font-bold} jest głównym językiem używanym w tej szkole" + "render_single_language": "Język {language()} jest głównym językiem używanym w tej szkole" } } }, diff --git a/langs/layers/pt.json b/langs/layers/pt.json index 3e2387dc4b..ebabfd54e0 100644 --- a/langs/layers/pt.json +++ b/langs/layers/pt.json @@ -500,7 +500,7 @@ "render": { "special": { "question": "Em que línguas este multibanco tem saída de fala?", - "render_list_item": "Este multibanco tem saída de fala em {language():font-bold}" + "render_list_item": "Este multibanco tem saída de fala em {language()}" } } } diff --git a/langs/layers/pt_BR.json b/langs/layers/pt_BR.json index a472d715cf..a15bc79e7a 100644 --- a/langs/layers/pt_BR.json +++ b/langs/layers/pt_BR.json @@ -489,8 +489,8 @@ "render": { "special": { "question": "Em quais línguas esse caixa eletrônico tem saída de fala?", - "render_list_item": "Este caixa eletrônico tem saída de fala em {language():font-bold}", - "render_single_language": "Este caixa eletrônico tem saída de fala em {language():font-bold}" + "render_list_item": "Este caixa eletrônico tem saída de fala em {language()}", + "render_single_language": "Este caixa eletrônico tem saída de fala em {language()}" } } } diff --git a/langs/themes/ca.json b/langs/themes/ca.json index 933eb133c3..a5cdfc921e 100644 --- a/langs/themes/ca.json +++ b/langs/themes/ca.json @@ -868,111 +868,6 @@ }, "title": "Vorals i encreuaments" }, - "mapcomplete-changes": { - "description": "Aquest mapa mostra tots els canvis fets amb MapComplete", - "layers": { - "0": { - "description": "Mostra tots els canvis de MapComplete", - "filter": { - "0": { - "options": { - "0": { - "question": "El nom del tema conté {search}" - } - } - }, - "2": { - "options": { - "0": { - "question": "Fet pel col·laborador {search}" - } - } - }, - "3": { - "options": { - "0": { - "question": "No fet pel col·laborador {search}" - } - } - }, - "4": { - "options": { - "0": { - "question": "Fet abans de {search}" - } - } - }, - "5": { - "options": { - "0": { - "question": "Fet després de {search}" - } - } - }, - "6": { - "options": { - "0": { - "question": "Idioma de l'usuari (codi iso) {search}" - } - } - }, - "7": { - "options": { - "0": { - "question": "Fet amb l'amfitrió {search}" - } - } - }, - "8": { - "options": { - "0": { - "question": "El conjunt de canvis ha afegit almenys una imatge" - } - } - } - }, - "tagRenderings": { - "contributor": { - "question": "Quin col·laborador va fer aquest canvi?", - "render": "Canvi fet per {user}" - }, - "host": { - "question": "Amb quin amfitrió (lloc web) es va fer aquest canvi?", - "render": "Canviat amb {host}" - }, - "locale": { - "question": "Amb quina configuració regional (idioma) s'ha fet aquest canvi?", - "render": "La configuració regional de l'usuari és {locale}" - }, - "show_changeset_id": { - "render": "Conjunt de canvi {id}" - }, - "theme-id": { - "question": "Quin tema es va utilitzar per fer aquest canvi?", - "render": "Canvi amb el tema {theme}" - }, - "version": { - "question": "Quina versió de MapComplete es va utilitzar per fer aquest canvi?", - "render": "Fet amb {editor}" - } - }, - "title": { - "render": "Conjunt de canvis per a {theme}" - } - }, - "1": { - "override": { - "tagRenderings+": { - "0": { - "render": "Es pot trobar més estadística aquí" - } - } - } - } - }, - "shortDescription": "Mostra els canvis fets amb MapComplete", - "title": "Canvis fets amb MapComplete" - }, "maproulette": { "description": "Tema que mostra les tasques de MapRoulette, que us permet cercar-les, filtrar-les i solucionar-les.", "title": "Tasques de MapRoulette" diff --git a/langs/themes/de.json b/langs/themes/de.json index 50b41becd7..598159fdfb 100644 --- a/langs/themes/de.json +++ b/langs/themes/de.json @@ -898,133 +898,6 @@ }, "title": "Bordsteine und Überwege" }, - "mapcomplete-changes": { - "description": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen", - "layers": { - "0": { - "description": "Zeigt alle MapComplete-Änderungen", - "filter": { - "0": { - "options": { - "0": { - "question": "Themename enthält {search}" - } - } - }, - "1": { - "options": { - "0": { - "question": "Der Name enthält nicht {search}" - } - } - }, - "2": { - "options": { - "0": { - "question": "Der Name enthält nicht {search}" - } - } - }, - "3": { - "options": { - "0": { - "question": "Nicht erstellt von {search}" - } - } - }, - "4": { - "options": { - "0": { - "question": "Erstellt vor {search}" - } - } - }, - "5": { - "options": { - "0": { - "question": "Erstellt nach {search}" - } - } - }, - "6": { - "options": { - "0": { - "question": "Benutzersprache (ISO-Code) {search}" - } - } - }, - "7": { - "options": { - "0": { - "question": "Erstellt mit Host {search}" - } - } - }, - "8": { - "options": { - "0": { - "question": "Änderungssatz hat mindestens ein Bild hinzugefügt" - } - } - }, - "9": { - "options": { - "0": { - "question": "GRB-Theme ausschließen" - } - } - }, - "10": { - "options": { - "0": { - "question": "Etymologie-Thema ausschließen" - } - } - } - }, - "name": "Zentrum der Änderungssätze", - "tagRenderings": { - "contributor": { - "question": "Wer hat diese Änderung vorgenommen?", - "render": "Änderung von {user}" - }, - "host": { - "question": "Über welchen Host (Webseite) wurde diese Änderung vorgenommen?", - "render": "Geändert über {host}" - }, - "locale": { - "question": "In welcher Benutzersprache wurde diese Änderung vorgenommen?", - "render": "Benutzersprache {locale}" - }, - "show_changeset_id": { - "render": "Änderungssatz {id}" - }, - "theme-id": { - "question": "Welches Theme wurde für diese Änderung verwendet?", - "render": "Geändert mit Thema {theme}" - }, - "version": { - "question": "Welche Version von MapComplete wurde verwendet, um diese Änderung vorzunehmen?", - "render": "Erstellt mit {editor}" - } - }, - "title": { - "render": "Änderungssatz für {theme}" - } - }, - "1": { - "override": { - "tagRenderings+": { - "0": { - "render": "Mehr Statistiken gibt es hier" - } - } - } - } - }, - "shortDescription": "Zeigt die von MapComplete vorgenommenen Änderungen an", - "title": "Mit MapComplete vorgenommene Änderungen" - }, "maproulette": { "description": "Thema mit MapRoulette-Aufgaben, die Sie suchen, filtern und beheben können.", "title": "MapRoulette-Aufgaben" diff --git a/langs/themes/en.json b/langs/themes/en.json index 391755f298..934d2de157 100644 --- a/langs/themes/en.json +++ b/langs/themes/en.json @@ -1129,6 +1129,57 @@ }, "title": "OnWheels" }, + "openlovemap": { + "description": "

Love in the palm of your hand

Open Love Map lists various adult entries, such as brothels, erotic stores and stripclubs.", + "layers": { + "2": { + "override": { + "=presets": { + "0": { + "title": "an erotic shop" + } + }, + "name": "Erotic shops" + } + }, + "4": { + "override": { + "=presets": { + "0": { + "title": "a condom vending machine" + } + } + } + }, + "6": { + "override": { + "=presets": { + "0": { + "title": "an erotic cinema" + } + } + } + }, + "9": { + "override": { + "+tagRenderings": { + "0": { + "question": "What type of hotel is this?" + } + } + } + } + }, + "overrideAll": { + "tagRenderings+": { + "0": { + "question": "Does {title()} have a private video booth?", + "questionHint": "This is for use by a single person." + } + } + }, + "title": "Open Love Map" + }, "openwindpowermap": { "description": "A map for showing and editing wind turbines.", "title": "Wind power generators" diff --git a/langs/themes/es.json b/langs/themes/es.json index 04f00ebcda..796941f9f8 100644 --- a/langs/themes/es.json +++ b/langs/themes/es.json @@ -898,23 +898,6 @@ }, "title": "Bordillos y cruces" }, - "mapcomplete-changes": { - "description": "Este mapa muestra todos los cambios realizados con MapComplete", - "layers": { - "0": { - "description": "Muestra todos los cambios de MapComplete", - "filter": { - "0": { - "options": { - "0": { - "question": "El nombre del tema contiene {search}" - } - } - } - } - } - } - }, "maproulette": { "description": "Tema que muestra las tareas de MapRoulette, permitiendo buscarlas, filtrarlas y arreglarlas.", "title": "Tareas de MapRoulette" diff --git a/src/Logic/FeatureSource/Sources/OverpassFeatureSource.ts b/src/Logic/FeatureSource/Sources/OverpassFeatureSource.ts index 51afcdfdd7..02ef73c435 100644 --- a/src/Logic/FeatureSource/Sources/OverpassFeatureSource.ts +++ b/src/Logic/FeatureSource/Sources/OverpassFeatureSource.ts @@ -103,7 +103,7 @@ export default class OverpassFeatureSource implements FeatureSource { if (!result) { return } - const [bounds, _, _] = result + const [bounds, _, __] = result this._lastQueryBBox = bounds } diff --git a/src/UI/Input/README.md b/src/UI/Input/README.md index 459e6c8565..82b6ff5477 100644 --- a/src/UI/Input/README.md +++ b/src/UI/Input/README.md @@ -1 +1 @@ -This is the old, deprecated directory. New, SVelte-based items go into `InputElement` +This is the old, deprecated directory. New, Svelte-based items go into `InputElement` diff --git a/src/UI/Input/SearchableMappingsSelector.ts b/src/UI/Input/SearchableMappingsSelector.ts deleted file mode 100644 index 8c41b32a64..0000000000 --- a/src/UI/Input/SearchableMappingsSelector.ts +++ /dev/null @@ -1,304 +0,0 @@ -import { UIElement } from "../UIElement" -import { InputElement } from "./InputElement" -import BaseUIElement from "../BaseUIElement" -import { Store, UIEventSource } from "../../Logic/UIEventSource" -import Translations from "../i18n/Translations" -import Locale from "../i18n/Locale" -import Combine from "../Base/Combine" -import { TextField } from "./TextField" -import Svg from "../../Svg" -import { VariableUiElement } from "../Base/VariableUIElement" - -/** - * A single 'pill' which can hide itself if the search criteria is not met - */ -class SelfHidingToggle extends UIElement implements InputElement { - public readonly _selected: UIEventSource - public readonly isShown: Store = new UIEventSource(true) - public readonly matchesSearchCriteria: Store - public readonly forceSelected: UIEventSource - private readonly _shown: BaseUIElement - private readonly _squared: boolean - - public constructor( - shown: string | BaseUIElement, - mainTerm: Record, - search: Store, - options?: { - searchTerms?: Record - selected?: UIEventSource - forceSelected?: UIEventSource - squared?: boolean - /* Hide, if not selected*/ - hide?: Store - } - ) { - super() - this._shown = Translations.W(shown) - this._squared = options?.squared ?? false - const searchTerms: Record = {} - for (const lng in options?.searchTerms ?? []) { - if (lng === "_context") { - continue - } - searchTerms[lng] = options?.searchTerms[lng]?.map(SelfHidingToggle.clean) - } - for (const lng in mainTerm) { - if (lng === "_context") { - continue - } - const main = SelfHidingToggle.clean(mainTerm[lng]) - searchTerms[lng] = [main].concat(searchTerms[lng] ?? []) - } - const selected = (this._selected = options?.selected ?? new UIEventSource(false)) - const forceSelected = (this.forceSelected = - options?.forceSelected ?? new UIEventSource(false)) - this.matchesSearchCriteria = search.map((s) => { - if (s === undefined || s.length === 0) { - return true - } - - s = s?.trim()?.toLowerCase() - if (searchTerms[Locale.language.data]?.some((t) => t.indexOf(s) >= 0)) { - return true - } - if (searchTerms["*"]?.some((t) => t.indexOf(s) >= 0)) { - return true - } - return false - }) - this.isShown = this.matchesSearchCriteria.map( - (matchesSearch) => { - if (selected.data && !forceSelected.data) { - return true - } - if (options?.hide?.data) { - return false - } - return matchesSearch - }, - [selected, Locale.language, options?.hide] - ) - - const self = this - this.isShown.addCallbackAndRun((shown) => { - if (shown) { - self.RemoveClass("hidden") - } else { - self.SetClass("hidden") - } - }) - } - - private static clean(s: string): string { - return s?.trim()?.toLowerCase()?.replace(/[-]/, "") - } - - GetValue(): UIEventSource { - return this._selected - } - - IsValid(_: boolean): boolean { - return true - } - - protected InnerRender(): string | BaseUIElement { - let el: BaseUIElement = this._shown - const selected = this._selected - - selected.addCallbackAndRun((selected) => { - if (selected) { - el.SetClass("border-4") - el.RemoveClass("border") - el.SetStyle("margin: 0") - } else { - el.SetStyle("margin: 3px") - el.SetClass("border") - el.RemoveClass("border-4") - } - }) - - const forcedSelection = this.forceSelected - el.onClick(() => { - if (forcedSelection.data) { - selected.setData(true) - } else { - selected.setData(!selected.data) - } - }) - - if (!this._squared) { - el.SetClass("rounded-full") - } - return el.SetClass("border border-black p-1 px-4") - } -} - -/** - * The searchable mappings selector is a selector which shows various pills from which one (or more) options can be chosen. - * A searchfield can be used to filter the values - */ -export class SearchablePillsSelector extends Combine implements InputElement { - public readonly someMatchFound: Store - private readonly selectedElements: UIEventSource - - /** - * - * @param values: the values that can be selected - * @param options - */ - constructor( - values: { - show: BaseUIElement - value: T - mainTerm: Record - searchTerms?: Record - /* If there are more then 200 elements, should this element still be shown? */ - hasPriority?: Store - }[], - options?: { - /* - * If one single value can be selected (like a radio button) or if many values can be selected (like checkboxes) - */ - mode?: "select-one" | "select-many" - /** - * The values of the selected elements. - * Use this to tie input elements together - */ - selectedElements?: UIEventSource - /** - * The search bar. Use this to seed the search value or to tie to another value - */ - searchValue?: UIEventSource - /** - * What is shown if the search yielded no results. - * By default: a translated "no search results" - */ - onNoMatches?: BaseUIElement - /** - * An element that is shown if no search is entered - * Default behaviour is to show all options - */ - onNoSearchMade?: BaseUIElement - /** - * Extra element to show if there are many (>200) possible mappings and when non-priority mappings are hidden - * - */ - onManyElements?: BaseUIElement - searchAreaClass?: string - hideSearchBar?: false | boolean - } - ) { - const search = new TextField({ value: options?.searchValue }) - - const searchBar = options?.hideSearchBar - ? undefined - : new Combine([ - Svg.search_svg().SetClass("w-8 normal-background"), - search.SetClass("w-full"), - ]).SetClass("flex items-center border-2 border-black m-2") - - const searchValue = search.GetValue().map((s) => s?.trim()?.toLowerCase()) - const selectedElements = options?.selectedElements ?? new UIEventSource([]) - const mode = options?.mode ?? "select-one" - const onEmpty = options?.onNoMatches ?? Translations.t.general.noMatchingMapping - const forceHide = new UIEventSource(false) - const mappedValues: { - show: SelfHidingToggle - mainTerm: Record - value: T - }[] = values.map((v) => { - const vIsSelected = new UIEventSource(false) - - selectedElements.addCallbackAndRunD((selectedElements) => { - vIsSelected.setData(selectedElements.some((t) => t === v.value)) - }) - - vIsSelected.addCallback((selected) => { - if (selected) { - if (mode === "select-one") { - selectedElements.setData([v.value]) - } else if (!selectedElements.data.some((t) => t === v.value)) { - selectedElements.data.push(v.value) - selectedElements.ping() - } - } else { - for (let i = 0; i < selectedElements.data.length; i++) { - const t = selectedElements.data[i] - if (t == v.value) { - selectedElements.data.splice(i, 1) - selectedElements.ping() - break - } - } - } - }) - - const toggle = new SelfHidingToggle(v.show, v.mainTerm, searchValue, { - searchTerms: v.searchTerms, - selected: vIsSelected, - squared: mode === "select-many", - hide: - v.hasPriority === undefined - ? forceHide - : forceHide.map((fh) => fh && !v.hasPriority?.data, [v.hasPriority]), - }) - - return { - ...v, - show: toggle, - } - }) - - // The total number of elements that would be displayed based on the search criteria alone - let totalShown: Store - totalShown = searchValue.map( - (_) => mappedValues.filter((mv) => mv.show.matchesSearchCriteria.data).length - ) - const tooMuchElementsCutoff = 40 - totalShown.addCallbackAndRunD((shown) => forceHide.setData(tooMuchElementsCutoff < shown)) - - super([ - searchBar, - new VariableUiElement( - Locale.language.map( - (lng) => { - if ( - options?.onNoSearchMade !== undefined && - (searchValue.data === undefined || searchValue.data.length === 0) - ) { - return options?.onNoSearchMade - } - if (totalShown.data == 0) { - return onEmpty - } - - mappedValues.sort((a, b) => (a.mainTerm[lng] < b.mainTerm[lng] ? -1 : 1)) - let pills = new Combine(mappedValues.map((e) => e.show)) - .SetClass("flex flex-wrap w-full content-start") - .SetClass(options?.searchAreaClass ?? "") - - if (totalShown.data >= tooMuchElementsCutoff) { - pills = new Combine([ - options?.onManyElements ?? Translations.t.general.useSearch, - pills, - ]) - } - return pills - }, - [totalShown, searchValue] - ) - ), - ]) - this.selectedElements = selectedElements - this.someMatchFound = totalShown.map((t) => t > 0) - } - - public GetValue(): UIEventSource { - return this.selectedElements - } - - IsValid(_: T[]): boolean { - return true - } -} diff --git a/src/UI/Popup/AllLanguagesSelector.ts b/src/UI/Popup/AllLanguagesSelector.ts deleted file mode 100644 index 3d3216e670..0000000000 --- a/src/UI/Popup/AllLanguagesSelector.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { SearchablePillsSelector } from "../Input/SearchableMappingsSelector" -import { Store } from "../../Logic/UIEventSource" -import BaseUIElement from "../BaseUIElement" -import all_languages from "../../assets/language_translations.json" -import { Translation } from "../i18n/Translation" - -export class AllLanguagesSelector extends SearchablePillsSelector { - constructor(options?: { - mode?: "select-many" | "select-one" - currentCountry?: Store - supportedLanguages?: Record & { _meta?: { countries?: string[] } } - }) { - const possibleValues: { - show: BaseUIElement - value: string - mainTerm: Record - searchTerms?: Record - hasPriority?: Store - }[] = [] - - const langs = options?.supportedLanguages ?? all_languages - for (const ln in langs) { - let languageInfo: Record & { _meta?: { countries: string[] } } = - all_languages[ln] - const countries = languageInfo._meta?.countries?.map((c) => c.toLowerCase()) - languageInfo = { ...languageInfo } - delete languageInfo._meta - const term = { - show: new Translation(languageInfo), - value: ln, - mainTerm: languageInfo, - searchTerms: { "*": [ln] }, - hasPriority: - countries === undefined - ? undefined - : options?.currentCountry?.map( - (country) => countries?.indexOf(country.toLowerCase()) >= 0 - ), - } - possibleValues.push(term) - } - super(possibleValues, { - mode: options?.mode ?? "select-many", - }) - } -} diff --git a/src/UI/Popup/LanguageElement.ts b/src/UI/Popup/LanguageElement.ts deleted file mode 100644 index a806faeede..0000000000 --- a/src/UI/Popup/LanguageElement.ts +++ /dev/null @@ -1,254 +0,0 @@ -import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization" -import BaseUIElement from "../BaseUIElement" -import { UIEventSource } from "../../Logic/UIEventSource" -import { VariableUiElement } from "../Base/VariableUIElement" -import all_languages from "../../assets/language_translations.json" -import { Translation } from "../i18n/Translation" -import Combine from "../Base/Combine" -import Title from "../Base/Title" -import Lazy from "../Base/Lazy" -import { SubstitutedTranslation } from "../SubstitutedTranslation" -import List from "../Base/List" -import { AllLanguagesSelector } from "./AllLanguagesSelector" -import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction" -import { And } from "../../Logic/Tags/And" -import { Tag } from "../../Logic/Tags/Tag" -import { EditButton, SaveButton } from "./SaveButton" -import Translations from "../i18n/Translations" -import Toggle from "../Input/Toggle" -import { Feature } from "geojson" -class xyz {} -export class LanguageElement implements SpecialVisualization { - funcName: string = "language_chooser" - needsUrls = [] - - docs: string | BaseUIElement = - "The language element allows to show and pick all known (modern) languages. The key can be set" - - args: { name: string; defaultValue?: string; doc: string; required?: boolean }[] = [ - { - name: "key", - required: true, - doc: "What key to use, e.g. `language`, `tactile_writing:braille:language`, ... If a language is supported, the language code will be appended to this key, resulting in `language:nl=yes` if nl is picked ", - }, - { - name: "question", - required: true, - doc: "What to ask if no questions are known", - }, - { - name: "render_list_item", - doc: "How a single language will be shown in the list of languages. Use `{language}` to indicate the language (which it must contain).", - defaultValue: "{language()}", - }, - { - name: "render_single_language", - doc: "What will be shown if the feature only supports a single language", - required: true, - }, - { - name: "render_all", - doc: "The full rendering. Use `{list}` to show where the list of languages must come. Optional if mode=single", - defaultValue: "{list()}", - }, - { - name: "no_known_languages", - doc: "The text that is shown if no languages are known for this key. If this text is omitted, the languages will be prompted instead", - }, - { - name: "mode", - doc: "If one or many languages can be selected. Should be 'multi' or 'single'", - defaultValue: "multi", - }, - ] - - example: ` - \`\`\`json - {"special": - "type": "language_chooser", - "key": "school:language", - "question": {"en": "What are the main (and administrative) languages spoken in this school?"}, - "render_single_language": {"en": "{language()} is spoken on this school"}, - "render_list_item": {"en": "{language()}"}, - "render_all": {"en": "The following languages are spoken here:{list()}"} - "mode":"multi" - } - \`\`\` - ` - - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature - ): BaseUIElement { - let [key, question, item_render, single_render, all_render, on_no_known_languages, mode] = - argument - if (mode === undefined || mode.length == 0) { - mode = "multi" - } - if (item_render === undefined || item_render.trim() === "") { - item_render = "{language()}" - } - if (all_render === undefined || all_render.length == 0) { - all_render = "{list()}" - } - if (mode !== "single" && mode !== "multi") { - throw ( - "Error while calling language_chooser: mode must be either 'single' or 'multi' but it is " + - mode - ) - } - if (single_render.indexOf("{language()") < 0) { - throw ( - "Error while calling language_chooser: render_single_language must contain '{language()}' but it is " + - single_render - ) - } - if (item_render.indexOf("{language()") < 0) { - throw ( - "Error while calling language_chooser: render_list_item must contain '{language()}' but it is " + - item_render - ) - } - if (all_render.indexOf("{list()") < 0) { - throw "Error while calling language_chooser: render_all must contain '{list()}'" - } - - const prefix = key + ":" - const foundLanguages = tagSource.map((tags) => { - const foundLanguages: string[] = [] - for (const k in tags) { - const v = tags[k] - if (v !== "yes") { - continue - } - if (k.startsWith(prefix)) { - foundLanguages.push(k.substring(prefix.length)) - } - } - return foundLanguages - }) - const forceInputMode = new UIEventSource(false) - const inputEl = new Lazy(() => { - const selector = new AllLanguagesSelector({ - mode: mode === "single" ? "select-one" : "select-many", - currentCountry: tagSource.map((tgs) => tgs["_country"]), - }) - const cancelButton = Toggle.If(forceInputMode, () => - Translations.t.general.cancel - .Clone() - .SetClass("btn btn-secondary") - .onClick(() => forceInputMode.setData(false)) - ) - - const saveButton = new SaveButton( - selector.GetValue().map((lngs) => (lngs.length > 0 ? "true" : undefined)), - state - ).onClick(() => { - const selectedLanguages = selector.GetValue().data - const currentLanguages = foundLanguages.data - const selection: Tag[] = selectedLanguages.map((ln) => new Tag(prefix + ln, "yes")) - - for (const currentLanguage of currentLanguages) { - if (selectedLanguages.indexOf(currentLanguage) >= 0) { - continue - } - // Erase language that is not spoken anymore - selection.push(new Tag(prefix + currentLanguage, "")) - } - - if (state.featureSwitchIsTesting.data) { - for (const tag of selection) { - tagSource.data[tag.key] = tag.value - } - tagSource.ping() - } else { - ;(state?.changes) - .applyAction( - new ChangeTagAction( - tagSource.data.id, - new And(selection), - tagSource.data, - { - theme: state?.layout?.id ?? "unkown", - changeType: "answer", - } - ) - ) - .then((_) => { - console.log("Tagchanges applied") - }) - } - forceInputMode.setData(false) - }) - - return new Combine([ - new Title(question), - selector, - new Combine([cancelButton, saveButton]).SetClass("flex justify-end"), - ]).SetClass("flex flex-col question disable-links") - }) - - const editButton = new EditButton(state.osmConnection, () => forceInputMode.setData(true)) - - return new VariableUiElement( - foundLanguages.map( - (foundLanguages) => { - if (forceInputMode.data) { - return inputEl - } - - if (foundLanguages.length === 0) { - // No languages found - we show the question and the input element - if ( - on_no_known_languages !== undefined && - on_no_known_languages.length > 0 - ) { - return new Combine([on_no_known_languages, editButton]).SetClass( - "flex justify-end" - ) - } - return inputEl - } - - let rendered: BaseUIElement - if (foundLanguages.length === 1) { - const ln = foundLanguages[0] - let mapping = new Map() - mapping.set("language", new Translation(all_languages[ln])) - rendered = new SubstitutedTranslation( - new Translation({ "*": single_render }, undefined), - tagSource, - state, - mapping - ) - } else { - let mapping = new Map() - const languagesList = new List( - foundLanguages.map((ln) => { - let mappingLn = new Map() - mappingLn.set("language", new Translation(all_languages[ln])) - return new SubstitutedTranslation( - new Translation({ "*": item_render }, undefined), - tagSource, - state, - mappingLn - ) - }) - ) - mapping.set("list", languagesList) - rendered = new SubstitutedTranslation( - new Translation({ "*": all_render }, undefined), - tagSource, - state, - mapping - ) - } - return new Combine([rendered, editButton]).SetClass("flex justify-between") - }, - [forceInputMode] - ) - ) - } -} diff --git a/src/UI/Popup/LanguageElement/LanguageAnswer.svelte b/src/UI/Popup/LanguageElement/LanguageAnswer.svelte new file mode 100644 index 0000000000..3a22365d62 --- /dev/null +++ b/src/UI/Popup/LanguageElement/LanguageAnswer.svelte @@ -0,0 +1,46 @@ + + +{#if $languages.length === 1} + +{:else} + {beforeListing} +
    + {#each $languages as language} +
  • + +
  • + {/each} +
+ {afterListing} +{/if} diff --git a/src/UI/Popup/LanguageElement/LanguageElement.svelte b/src/UI/Popup/LanguageElement/LanguageElement.svelte new file mode 100644 index 0000000000..c2cce0beb9 --- /dev/null +++ b/src/UI/Popup/LanguageElement/LanguageElement.svelte @@ -0,0 +1,69 @@ + + +{#if $foundLanguages.length === 0 && on_no_known_languages && !$forceInputMode} +
+
+ {on_no_known_languages} +
+ forceInputMode.setData(true)} /> +
+{:else if $forceInputMode || $foundLanguages.length === 0} + forceInputMode.setData(false)}> + + {#if $forceInputMode} + + {/if} + + +{:else} +
+
+ +
+ forceInputMode.setData(true)} /> +
+{/if} diff --git a/src/UI/Popup/LanguageElement/LanguageElement.ts b/src/UI/Popup/LanguageElement/LanguageElement.ts new file mode 100644 index 0000000000..1f2dc8c6b5 --- /dev/null +++ b/src/UI/Popup/LanguageElement/LanguageElement.ts @@ -0,0 +1,107 @@ +import { SpecialVisualization, SpecialVisualizationState } from "../../SpecialVisualization" +import BaseUIElement from "../../BaseUIElement" +import { UIEventSource } from "../../../Logic/UIEventSource" +import SvelteUIElement from "../../Base/SvelteUIElement" +import { Feature } from "geojson" +import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" +import { default as LanguageElementSvelte } from "./LanguageElement.svelte" + +export class LanguageElement implements SpecialVisualization { + funcName: string = "language_chooser" + needsUrls = [] + + docs: string | BaseUIElement = + "The language element allows to show and pick all known (modern) languages. The key can be set" + + args: { name: string; defaultValue?: string; doc: string; required?: boolean }[] = [ + { + name: "key", + required: true, + doc: "What key to use, e.g. `language`, `tactile_writing:braille:language`, ... If a language is supported, the language code will be appended to this key, resulting in `language:nl=yes` if nl is picked ", + }, + { + name: "question", + required: true, + doc: "What to ask if no questions are known", + }, + { + name: "render_list_item", + doc: "How a single language will be shown in the list of languages. Use `{language}` to indicate the language (which it must contain).", + defaultValue: "{language()}", + }, + { + name: "render_single_language", + doc: "What will be shown if the feature only supports a single language", + required: true, + }, + { + name: "render_all", + doc: "The full rendering. Use `{list}` to show where the list of languages must come. Optional if mode=single", + defaultValue: "{list()}", + }, + { + name: "no_known_languages", + doc: "The text that is shown if no languages are known for this key. If this text is omitted, the languages will be prompted instead", + }, + ] + + example: ` + \`\`\`json + {"special": + "type": "language_chooser", + "key": "school:language", + "question": {"en": "What are the main (and administrative) languages spoken in this school?"}, + "render_single_language": {"en": "{language()} is spoken on this school"}, + "render_list_item": {"en": "{language()}"}, + "render_all": {"en": "The following languages are spoken here:{list()}"} + } + \`\`\` + ` + + constr( + state: SpecialVisualizationState, + tagSource: UIEventSource>, + argument: string[], + feature: Feature, + layer: LayerConfig + ): BaseUIElement { + let [key, question, item_render, single_render, all_render, on_no_known_languages] = + argument + if (item_render === undefined || item_render.trim() === "") { + item_render = "{language()}" + } + if (all_render === undefined || all_render.length == 0) { + all_render = "{list()}" + } + if (single_render.indexOf("{language()") < 0) { + throw ( + "Error while calling language_chooser: render_single_language must contain '{language()}' but it is " + + single_render + ) + } + if (item_render.indexOf("{language()") < 0) { + throw ( + "Error while calling language_chooser: render_list_item must contain '{language()}' but it is " + + item_render + ) + } + if (all_render.indexOf("{list()") < 0) { + throw "Error while calling language_chooser: render_all must contain '{list()}'" + } + if (on_no_known_languages === "") { + on_no_known_languages = undefined + } + + return new SvelteUIElement(LanguageElementSvelte, { + key, + tags: tagSource, + state, + feature, + layer, + question, + on_no_known_languages, + single_render, + item_render, + }) + } +} diff --git a/src/UI/Popup/LanguageElement/LanguageOptions.svelte b/src/UI/Popup/LanguageElement/LanguageOptions.svelte new file mode 100644 index 0000000000..62f78b776f --- /dev/null +++ b/src/UI/Popup/LanguageElement/LanguageOptions.svelte @@ -0,0 +1,133 @@ + +
onEnter()}> + + {#each probableLanguages as lng} + + + + {/each} + + + +
+ {#each knownLanguagecodes as lng} + {#if (isChecked[lng]) && $newlyChecked.indexOf(lng) < 0 && probableLanguages.indexOf(lng) < 0} + + + {/if} + {/each} + + {#each knownLanguagecodes as lng} + {#if $searchLC.length > 0 && matchesSearch(lng, $searchLC) && (!isChecked[lng] || $newlyChecked.indexOf(lng) >= 0) && probableLanguages.indexOf(lng) < 0} + + + {/if} + {/each} +
+
diff --git a/src/UI/Popup/LanguageElement/LanguageQuestion.svelte b/src/UI/Popup/LanguageElement/LanguageQuestion.svelte new file mode 100644 index 0000000000..5cd892ff73 --- /dev/null +++ b/src/UI/Popup/LanguageElement/LanguageQuestion.svelte @@ -0,0 +1,87 @@ + + + diff --git a/src/UI/Popup/SaveButton.ts b/src/UI/Popup/SaveButton.ts deleted file mode 100644 index 26a36ca896..0000000000 --- a/src/UI/Popup/SaveButton.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Store } from "../../Logic/UIEventSource" -import Translations from "../i18n/Translations" -import { OsmConnection } from "../../Logic/Osm/OsmConnection" -import Toggle from "../Input/Toggle" -import BaseUIElement from "../BaseUIElement" -import Combine from "../Base/Combine" -import Svg from "../../Svg" -import { LoginToggle } from "./LoginButton" - -export class EditButton extends Toggle { - constructor(osmConnection: OsmConnection, onClick: () => void) { - super( - new Combine([Svg.pencil_svg()]) - .SetClass("block relative h-10 w-10 p-2 float-right") - .SetStyle("border: 1px solid black; border-radius: 0.7em") - .onClick(onClick), - undefined, - osmConnection.isLoggedIn - ) - } -} - -export class SaveButton extends LoginToggle { - constructor( - value: Store, - state: { - readonly osmConnection?: OsmConnection - readonly featureSwitchUserbadge?: Store - }, - textEnabled?: BaseUIElement, - textDisabled?: BaseUIElement - ) { - if (value === undefined) { - throw "No event source for savebutton, something is wrong" - } - - const isSaveable = value.map((v) => v !== false && (v ?? "") !== "") - - const saveEnabled = (textEnabled ?? Translations.t.general.save.Clone()).SetClass(`btn`) - const saveDisabled = (textDisabled ?? Translations.t.general.save.Clone()).SetClass( - `btn btn-disabled` - ) - - const save = new Toggle(saveEnabled, saveDisabled, isSaveable) - super(save, Translations.t.general.loginToStart, state) - } -} diff --git a/src/UI/Popup/TagRendering/EditButton.svelte b/src/UI/Popup/TagRendering/EditButton.svelte new file mode 100644 index 0000000000..031680583c --- /dev/null +++ b/src/UI/Popup/TagRendering/EditButton.svelte @@ -0,0 +1,23 @@ + + + diff --git a/src/UI/Popup/TagRendering/TagRenderingEditable.svelte b/src/UI/Popup/TagRendering/TagRenderingEditable.svelte index bf233b0e66..c2312021c9 100644 --- a/src/UI/Popup/TagRendering/TagRenderingEditable.svelte +++ b/src/UI/Popup/TagRendering/TagRenderingEditable.svelte @@ -13,6 +13,8 @@ import { Utils } from "../../../Utils" import { twMerge } from "tailwind-merge" import { ariaLabel } from "../../../Utils/ariaLabel" + import EditButton from "./EditButton.svelte" + import EditItemButton from "../../Studio/EditItemButton.svelte" export let config: TagRenderingConfig export let tags: UIEventSource> @@ -102,16 +104,12 @@ {:else}
- + editMode = true + }}/>
{/if} {:else} diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index 9145ef99a6..c94a1a3ce2 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -31,11 +31,10 @@ import OpeningHoursVisualization from "./OpeningHours/OpeningHoursVisualization" import { SubtleButton } from "./Base/SubtleButton" import Svg from "../Svg" import NoteCommentElement from "./Popup/Notes/NoteCommentElement" -import { SubstitutedTranslation } from "./SubstitutedTranslation" import List from "./Base/List" import StatisticsPanel from "./BigComponents/StatisticsPanel" import AutoApplyButton from "./Popup/AutoApplyButton" -import { LanguageElement } from "./Popup/LanguageElement" +import { LanguageElement } from "./Popup/LanguageElement/LanguageElement" import FeatureReviews from "../Logic/Web/MangroveReviews" import Maproulette from "../Logic/Maproulette" import SvelteUIElement from "./Base/SvelteUIElement" @@ -88,6 +87,7 @@ import MaprouletteSetStatus from "./MapRoulette/MaprouletteSetStatus.svelte" import DirectionIndicator from "./Base/DirectionIndicator.svelte" import Img from "./Base/Img" import Qr from "../Utils/Qr" +import SpecialTranslation from "./Popup/TagRendering/SpecialTranslation.svelte" class NearbyImageVis implements SpecialVisualization { // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests @@ -1044,20 +1044,28 @@ export default class SpecialVisualizations { docs: "Shows the title of the popup. Useful for some cases, e.g. 'What is phone number of {title()}?'", example: "`What is the phone number of {title()}`, which might automatically become `What is the phone number of XYZ`.", - constr: (state, tagsSource) => + constr: ( + state: SpecialVisualizationState, + tagsSource: UIEventSource>, + _: string[], + feature: Feature, + layer: LayerConfig + ) => new VariableUiElement( tagsSource.map((tags) => { if (state.layout === undefined) { return "" } - const layer = state.layout?.getMatchingLayer(tags) const title = layer?.title?.GetRenderValue(tags) if (title === undefined) { return undefined } - return new SubstitutedTranslation(title, tagsSource, state).SetClass( - "px-1" - ) + return new SvelteUIElement(SpecialTranslation, { + tags: tagsSource, + state, + feature, + layer, + }).SetClass("px-1") }) ), }, @@ -1311,7 +1319,13 @@ export default class SpecialVisualizations { required: true, }, ], - constr(state, featureTags, args) { + constr( + state: SpecialVisualizationState, + featureTags: UIEventSource>, + args: string[], + feature: Feature, + layer: LayerConfig + ) { const [key, tr] = args const translation = new Translation({ "*": tr }) return new VariableUiElement( @@ -1319,11 +1333,13 @@ export default class SpecialVisualizations { const properties: object[] = JSON.parse(tags[key]) const elements = [] for (const property of properties) { - const subsTr = new SubstitutedTranslation( - translation, - new UIEventSource(property), - state - ) + const subsTr = new SvelteUIElement(SpecialTranslation, { + t: translation, + tags: properties, + state, + feature, + layer, + }) elements.push(subsTr) } return new List(elements) diff --git a/src/UI/SubstitutedTranslation.ts b/src/UI/SubstitutedTranslation.ts deleted file mode 100644 index 05325e4023..0000000000 --- a/src/UI/SubstitutedTranslation.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { UIEventSource } from "../Logic/UIEventSource" -import { Translation } from "./i18n/Translation" -import Locale from "./i18n/Locale" -import { FixedUiElement } from "./Base/FixedUiElement" -import { Utils } from "../Utils" -import { VariableUiElement } from "./Base/VariableUIElement" -import Combine from "./Base/Combine" -import BaseUIElement from "./BaseUIElement" -import LinkToWeblate from "./Base/LinkToWeblate" -import { SpecialVisualization, SpecialVisualizationState } from "./SpecialVisualization" -import SpecialVisualizations from "./SpecialVisualizations" -import { Feature } from "geojson" -import LayerConfig from "../Models/ThemeConfig/LayerConfig" - -/** - * @deprecated - use 'SpecialTranslation' instead - */ -export class SubstitutedTranslation extends VariableUiElement { - public constructor( - translation: Translation, - tagsSource: UIEventSource>, - state: SpecialVisualizationState, - mapping: Map< - string, - | BaseUIElement - | (( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ) => BaseUIElement) - > = undefined - ) { - const extraMappings: SpecialVisualization[] = [] - - mapping?.forEach((value, key) => { - extraMappings.push({ - funcName: key, - constr: typeof value === "function" ? value : () => value, - docs: "Dynamically injected input element", - args: [], - needsUrls: [], - example: "", - }) - }) - - const linkToWeblate = - translation !== undefined - ? new LinkToWeblate(translation.context, translation.translations) - : undefined - - super( - Locale.language.map((language) => { - let txt = translation?.textFor(language) - if (txt === undefined) { - return undefined - } - mapping?.forEach((_, key) => { - txt = txt.replace(new RegExp(`{${key}}`, "g"), `{${key}()}`) - }) - - const allElements = SpecialVisualizations.constructSpecification( - txt, - extraMappings - ).map((proto) => { - if (typeof proto === "string") { - if (tagsSource === undefined) { - return Utils.SubstituteKeys(proto, undefined) - } - return new VariableUiElement( - tagsSource.map((tags) => Utils.SubstituteKeys(proto, tags)) - ) - } - const viz: { - func: SpecialVisualization - args: string[] - style: string - } = proto - if (viz === undefined) { - console.error( - "SPECIALRENDERING UNDEFINED for", - tagsSource.data?.id, - "THIS IS REALLY WEIRD" - ) - return undefined - } - try { - const feature = state.indexedFeatures.featuresById.data.get( - tagsSource.data.id - ) - return viz.func - .constr( - state, - tagsSource, - proto.args.map((t) => SpecialVisualizations.undoEncoding(t)), - feature, - undefined - ) - ?.SetStyle(proto.style) - } catch (e) { - console.error("SPECIALRENDERING FAILED for", tagsSource.data?.id, e) - return new FixedUiElement( - `Could not generate special rendering for ${ - viz.func.funcName - }(${viz.args.join(", ")}) ${e}` - ).SetStyle("alert") - } - }) - allElements.push(linkToWeblate) - - return new Combine(allElements) - }) - ) - - this.SetClass("w-full") - } -} diff --git a/src/UI/Test.svelte b/src/UI/Test.svelte index c4d5d18230..29acbc7d67 100644 --- a/src/UI/Test.svelte +++ b/src/UI/Test.svelte @@ -1,7 +1,16 @@ - + + diff --git a/src/UI/i18n/Translation.ts b/src/UI/i18n/Translation.ts index 806ce0ceea..96145adb57 100644 --- a/src/UI/i18n/Translation.ts +++ b/src/UI/i18n/Translation.ts @@ -9,8 +9,6 @@ export class Translation extends BaseUIElement { public readonly translations: Record public readonly context?: string - - private _current: Store private onDestroy: () => void constructor(translations: string | Record, context?: string) { @@ -43,9 +41,11 @@ export class Translation extends BaseUIElement { console.error( "Non-string object at", context, + "of type", + typeof translations[translationsKey], `for language`, translationsKey, - `in translation: `, + `. The offending object is: `, translations[translationsKey], "\n current translations are: ", translations @@ -66,9 +66,7 @@ export class Translation extends BaseUIElement { } } - get txt(): string { - return this.textFor(Translation.forcedLanguage ?? Locale.language.data) - } + private _current: Store get current(): Store { if (!this._current) { @@ -82,6 +80,11 @@ export class Translation extends BaseUIElement { } return this._current } + + get txt(): string { + return this.textFor(Translation.forcedLanguage ?? Locale.language.data) + } + static ExtractAllTranslationsFrom( object: any, context = "" @@ -368,4 +371,32 @@ export class TypedTranslation> extends Translation return new TypedTranslation>(newTranslations, this.context) } + + PartialSubsTr( + key: string, + replaceWith: Translation + ): TypedTranslation> { + const newTranslations: Record = {} + const toSearch = "{" + key + "}" + const missingLanguages = new Set(Object.keys(this.translations)) + for (const lang in this.translations) { + missingLanguages.delete(lang) + const template = this.translations[lang] + if (lang === "_context") { + newTranslations[lang] = template + continue + } + const v = replaceWith.textFor(lang) + newTranslations[lang] = template.replaceAll(toSearch, v) + } + const baseTemplate = this.textFor("en") + for (const missingLanguage of missingLanguages) { + newTranslations[missingLanguage] = baseTemplate.replaceAll( + toSearch, + replaceWith.textFor(missingLanguage) + ) + } + + return new TypedTranslation>(newTranslations, this.context) + } }