forked from MapComplete/MapComplete
Refactoring: convert language input element into svelte,remove many obsolete classes
This commit is contained in:
parent
e68b31e267
commit
2e8b44659a
36 changed files with 1038 additions and 1412 deletions
|
@ -581,25 +581,25 @@
|
||||||
"pt": "Em que línguas este multibanco tem saída de fala?"
|
"pt": "Em que línguas este multibanco tem saída de fala?"
|
||||||
},
|
},
|
||||||
"render_list_item": {
|
"render_list_item": {
|
||||||
"en": "This ATM has speech output in {language():font-bold}",
|
"en": "This ATM has speech output in {language()}",
|
||||||
"de": "Dieser Geldautomat hat eine Sprachausgabe in {language():font-bold}",
|
"de": "Dieser Geldautomat hat eine Sprachausgabe in {language()}",
|
||||||
"nl": "Deze geldautomaat heeft spraak in {language():font-bold}",
|
"nl": "Deze geldautomaat heeft spraak in {language()}",
|
||||||
"ca": "Aquest caixer té sortida de veu en {language():font-bold}",
|
"ca": "Aquest caixer té sortida de veu en {language()}",
|
||||||
"cs": "Tento bankomat má řečový výstup v {language():font-bold}",
|
"cs": "Tento bankomat má řečový výstup v {language()}",
|
||||||
"he": "לכספומט הזה יש פלט דיבור ב {language():font-bold}",
|
"he": "לכספומט הזה יש פלט דיבור ב {language()}",
|
||||||
"pt_BR": "Este caixa eletrônico tem saída de fala em {language():font-bold}",
|
"pt_BR": "Este caixa eletrônico tem saída de fala em {language()}",
|
||||||
"es": "Este cajero automático tiene salida de voz en {language():font-bold}",
|
"es": "Este cajero automático tiene salida de voz en {language()}",
|
||||||
"pt": "Este multibanco tem saída de fala em {language():font-bold}"
|
"pt": "Este multibanco tem saída de fala em {language()}"
|
||||||
},
|
},
|
||||||
"render_single_language": {
|
"render_single_language": {
|
||||||
"en": "This ATM has speech output in {language():font-bold}",
|
"en": "This ATM has speech output in {language()}",
|
||||||
"de": "Dieser Geldautomat hat eine Sprachausgabe in {language():font-bold}",
|
"de": "Dieser Geldautomat hat eine Sprachausgabe in {language()}",
|
||||||
"nl": "Deze automaat heeft spraak in {language():font-bold}",
|
"nl": "Deze automaat heeft spraak in {language()}",
|
||||||
"ca": "Aquest caixer té sortida de veu en {language():font-bold}",
|
"ca": "Aquest caixer té sortida de veu en {language()}",
|
||||||
"cs": "Tento bankomat má řečový výstup v {language():font-bold}",
|
"cs": "Tento bankomat má řečový výstup v {language()}",
|
||||||
"he": "לכספומט הזה יש פלט דיבור ב {language():font-bold}",
|
"he": "לכספומט הזה יש פלט דיבור ב {language()}",
|
||||||
"pt_BR": "Este caixa eletrônico tem saída de fala em {language():font-bold}",
|
"pt_BR": "Este caixa eletrônico tem saída de fala em {language()}",
|
||||||
"es": "Este cajero automático tiene salida de voz en {language():font-bold}"
|
"es": "Este cajero automático tiene salida de voz en {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,18 +267,18 @@
|
||||||
"cs": "Ve kterých jazycích má tento výtah hmatové písmo (braillovo písmo)?"
|
"cs": "Ve kterých jazycích má tento výtah hmatové písmo (braillovo písmo)?"
|
||||||
},
|
},
|
||||||
"render_list_item": {
|
"render_list_item": {
|
||||||
"en": "This elevator has tactile writing in {language():font-bold}",
|
"en": "This elevator has tactile writing in {language()}",
|
||||||
"de": "Der Aufzug hat taktile Schrift in {language():font-bold}",
|
"de": "Der Aufzug hat taktile Schrift in {language()}",
|
||||||
"nl": "Deze lift heeft voelbaar schrift in het {language():font-bold}",
|
"nl": "Deze lift heeft voelbaar schrift in het {language()}",
|
||||||
"ca": "Aquest ascensor té l'escriptura tàctil en {language():font-bold}",
|
"ca": "Aquest ascensor té l'escriptura tàctil en {language()}",
|
||||||
"cs": "Tento výtah má hmatové písmo v {language():font-bold}"
|
"cs": "Tento výtah má hmatové písmo v {language()}"
|
||||||
},
|
},
|
||||||
"render_single_language": {
|
"render_single_language": {
|
||||||
"en": "This elevator has tactile writing in {language():font-bold}",
|
"en": "This elevator has tactile writing in {language()}",
|
||||||
"de": "Der Aufzug hat taktile Schrift in {language():font-bold}",
|
"de": "Der Aufzug hat taktile Schrift in {language()}",
|
||||||
"nl": "Deze lift heeft voelbaar schrift in het {language():font-bold}",
|
"nl": "Deze lift heeft voelbaar schrift in het {language()}",
|
||||||
"ca": "Aquest ascensor té l'escriptura tàctil en {language():font-bold}",
|
"ca": "Aquest ascensor té l'escriptura tàctil en {language()}",
|
||||||
"cs": "Tento výtah má hmatové písmo v {language():font-bold}"
|
"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?"
|
"cs": "Ve kterých jazycích má tento výtah hlasový výstup?"
|
||||||
},
|
},
|
||||||
"render_list_item": {
|
"render_list_item": {
|
||||||
"en": "This elevator has speech output in {language():font-bold}",
|
"en": "This elevator has speech output in {language()}",
|
||||||
"nl": "Deze lift heeft gesproken tekst in het {language():font-bold}",
|
"nl": "Deze lift heeft gesproken tekst in het {language()}",
|
||||||
"de": "Der Aufzug hat eine Sprachausgabe in {language():font-bold}",
|
"de": "Der Aufzug hat eine Sprachausgabe in {language()}",
|
||||||
"ca": "Aquest ascensor té sortida de veu en {language():font-bold}",
|
"ca": "Aquest ascensor té sortida de veu en {language()}",
|
||||||
"cs": "Tento výtah má hlasový výstup v {language():font-bold}"
|
"cs": "Tento výtah má hlasový výstup v {language()}"
|
||||||
},
|
},
|
||||||
"render_single_language": {
|
"render_single_language": {
|
||||||
"en": "This elevator has speech output in {language():font-bold}",
|
"en": "This elevator has speech output in {language()}",
|
||||||
"nl": "Deze lift heeft gesproken tekst in het {language():font-bold}",
|
"nl": "Deze lift heeft gesproken tekst in het {language()}",
|
||||||
"de": "Der Aufzug hat eine Sprachausgabe in {language():font-bold}",
|
"de": "Der Aufzug hat eine Sprachausgabe in {language()}",
|
||||||
"ca": "Aquest ascensor té sortida de veu en {language():font-bold}",
|
"ca": "Aquest ascensor té sortida de veu en {language()}",
|
||||||
"cs": "Tento výtah má hlasový výstup v {language():font-bold}"
|
"cs": "Tento výtah má hlasový výstup v {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,12 +435,12 @@
|
||||||
"cs": "V této škole se používají následující jazyky:{list()}"
|
"cs": "V této škole se používají následující jazyky:{list()}"
|
||||||
},
|
},
|
||||||
"render_single_language": {
|
"render_single_language": {
|
||||||
"en": "{language():font-bold} is the main language of this school",
|
"en": "{language()} is the main language of this school",
|
||||||
"de": "{language():font-bold} ist die Hauptsprache der Schule",
|
"de": "{language()} ist die Hauptsprache der Schule",
|
||||||
"ca": "{language():font-bold} és la llengua principal d'aquesta escola",
|
"ca": "{language()} és la llengua principal d'aquesta escola",
|
||||||
"fr": "{language():font-bold} est la langue principale dans cette école",
|
"fr": "{language()} est la langue principale dans cette école",
|
||||||
"pl": "Język {language():font-bold} jest głównym językiem używanym w tej szkole",
|
"pl": "Język {language()} jest głównym językiem używanym w tej szkole",
|
||||||
"cs": "{language():font-bold} je hlavním jazykem této školy"
|
"cs": "{language()} je hlavním jazykem této školy"
|
||||||
},
|
},
|
||||||
"question": {
|
"question": {
|
||||||
"en": "What is the main language of this school?<div class='subtle'>What language is spoken with the students in non-language related courses and with the administration?</div>",
|
"en": "What is the main language of this school?<div class='subtle'>What language is spoken with the students in non-language related courses and with the administration?</div>",
|
||||||
|
|
|
@ -205,18 +205,18 @@
|
||||||
"cs": "Ve kterých jazycích existuje hmatové písmo (braillské písmo) pro navigaci? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />"
|
"cs": "Ve kterých jazycích existuje hmatové písmo (braillské písmo) pro navigaci? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />"
|
||||||
},
|
},
|
||||||
"render_list_item": {
|
"render_list_item": {
|
||||||
"en": "These stairs have tactile writing in {language():font-bold}",
|
"en": "These stairs have tactile writing in {language()}",
|
||||||
"de": "Die Treppe hat taktile Schrift in {language():font-bold}",
|
"de": "Die Treppe hat taktile Schrift in {language()}",
|
||||||
"nl": "Deze trap heeft voelbaar schrijft in {language():font-bold}",
|
"nl": "Deze trap heeft voelbaar schrijft in {language()}",
|
||||||
"ca": "Aquestes escales tenen escriptura tàctil en {language():font-bold}",
|
"ca": "Aquestes escales tenen escriptura tàctil en {language()}",
|
||||||
"cs": "Tyto schody mají hmatové písmo v {language():font-bold}"
|
"cs": "Tyto schody mají hmatové písmo v {language()}"
|
||||||
},
|
},
|
||||||
"render_single_language": {
|
"render_single_language": {
|
||||||
"en": "These stairs have tactile writing in {language():font-bold}",
|
"en": "These stairs have tactile writing in {language()}",
|
||||||
"de": "Die Treppe hat taktile Schrift in {language():font-bold}",
|
"de": "Die Treppe hat taktile Schrift in {language()}",
|
||||||
"nl": "Deze trap heeft voelbaar schrijft in {language():font-bold}",
|
"nl": "Deze trap heeft voelbaar schrijft in {language()}",
|
||||||
"ca": "Aquestes escales tenen escriptura tàctil en {language():font-bold}",
|
"ca": "Aquestes escales tenen escriptura tàctil en {language()}",
|
||||||
"cs": "Tyto schody mají hmatové písmo v {language():font-bold}"
|
"cs": "Tyto schody mají hmatové písmo v {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,16 +35,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"title": "un mupi"
|
"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": {
|
"2": {
|
||||||
"title": "un mupi sobre la paret"
|
"title": "un mupi sobre la paret"
|
||||||
},
|
},
|
||||||
|
@ -71,6 +61,16 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"title": "un tòtem"
|
"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": {
|
"tagRenderings": {
|
||||||
|
@ -165,9 +165,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Açò és un tauló d'anunis"
|
"then": "Açò és un tauló d'anunis"
|
||||||
},
|
},
|
||||||
"10": {
|
|
||||||
"then": "Açò és una paret pintada"
|
|
||||||
},
|
|
||||||
"2": {
|
"2": {
|
||||||
"then": "Açò és una columna"
|
"then": "Açò és una columna"
|
||||||
},
|
},
|
||||||
|
@ -191,6 +188,9 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Açò és un tòtem"
|
"then": "Açò és un tòtem"
|
||||||
|
},
|
||||||
|
"10": {
|
||||||
|
"then": "Açò és una paret pintada"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"question": "Quin tipus d'element publicitari és aquest?",
|
"question": "Quin tipus d'element publicitari és aquest?",
|
||||||
|
@ -205,9 +205,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Tauló d'anuncis"
|
"then": "Tauló d'anuncis"
|
||||||
},
|
},
|
||||||
"10": {
|
|
||||||
"then": "Paret Pintada"
|
|
||||||
},
|
|
||||||
"2": {
|
"2": {
|
||||||
"then": "Mupi"
|
"then": "Mupi"
|
||||||
},
|
},
|
||||||
|
@ -231,6 +228,9 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Tòtem"
|
"then": "Tòtem"
|
||||||
|
},
|
||||||
|
"10": {
|
||||||
|
"then": "Paret Pintada"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,15 +351,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Mural"
|
"then": "Mural"
|
||||||
},
|
},
|
||||||
"10": {
|
|
||||||
"then": "Azulejo (Rajoles decoratives espanyoles i portugueses)"
|
|
||||||
},
|
|
||||||
"11": {
|
|
||||||
"then": "Enrajolat"
|
|
||||||
},
|
|
||||||
"12": {
|
|
||||||
"then": "Tallat a la fusta"
|
|
||||||
},
|
|
||||||
"2": {
|
"2": {
|
||||||
"then": "Pintura"
|
"then": "Pintura"
|
||||||
},
|
},
|
||||||
|
@ -383,6 +374,15 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Relleu"
|
"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?",
|
"question": "Quin tipus d'obra és aquesta peça?",
|
||||||
|
@ -528,8 +528,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "En quins idiomes té sortida de veu aquest caixer?",
|
"question": "En quins idiomes té sortida de veu aquest caixer?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Aquest caixer té sortida de veu en {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1920,30 +1920,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "<b>Endoll de paret Schuko</b> sense pin a terra (CEE7/4 tipus F)"
|
"then": "<b>Endoll de paret Schuko</b> sense pin a terra (CEE7/4 tipus F)"
|
||||||
},
|
},
|
||||||
"10": {
|
|
||||||
"then": "<b>CSS Tipus 1</b> (també conegut com a Tipus 1 Combo)"
|
|
||||||
},
|
|
||||||
"11": {
|
|
||||||
"then": "<b>CSS Tipus 1</b> (també conegut com a Tipus 1 Combo)"
|
|
||||||
},
|
|
||||||
"12": {
|
|
||||||
"then": "<b>Supercarregador de Tesla"
|
|
||||||
},
|
|
||||||
"13": {
|
|
||||||
"then": "<b>Supercarregador de Tesla</b>"
|
|
||||||
},
|
|
||||||
"14": {
|
|
||||||
"then": "<b>Tipus 2</b> (mennekes)"
|
|
||||||
},
|
|
||||||
"15": {
|
|
||||||
"then": "<b>Tipus 2</b> (mennekes)"
|
|
||||||
},
|
|
||||||
"16": {
|
|
||||||
"then": "<b>CSS Tipus 2</b> (mennekes)"
|
|
||||||
},
|
|
||||||
"17": {
|
|
||||||
"then": "<b>CSS Tipus 2</b> (mennekes)"
|
|
||||||
},
|
|
||||||
"2": {
|
"2": {
|
||||||
"then": "<b>Endoll de paret Europeu</b> amb pin a terra (CEE7/4 tipus E)"
|
"then": "<b>Endoll de paret Europeu</b> amb pin a terra (CEE7/4 tipus E)"
|
||||||
},
|
},
|
||||||
|
@ -1967,6 +1943,30 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "<b>Tipus 1 <i>sense</i> cable</b>(J1772)"
|
"then": "<b>Tipus 1 <i>sense</i> cable</b>(J1772)"
|
||||||
|
},
|
||||||
|
"10": {
|
||||||
|
"then": "<b>CSS Tipus 1</b> (també conegut com a Tipus 1 Combo)"
|
||||||
|
},
|
||||||
|
"11": {
|
||||||
|
"then": "<b>CSS Tipus 1</b> (també conegut com a Tipus 1 Combo)"
|
||||||
|
},
|
||||||
|
"12": {
|
||||||
|
"then": "<b>Supercarregador de Tesla"
|
||||||
|
},
|
||||||
|
"13": {
|
||||||
|
"then": "<b>Supercarregador de Tesla</b>"
|
||||||
|
},
|
||||||
|
"14": {
|
||||||
|
"then": "<b>Tipus 2</b> (mennekes)"
|
||||||
|
},
|
||||||
|
"15": {
|
||||||
|
"then": "<b>Tipus 2</b> (mennekes)"
|
||||||
|
},
|
||||||
|
"16": {
|
||||||
|
"then": "<b>CSS Tipus 2</b> (mennekes)"
|
||||||
|
},
|
||||||
|
"17": {
|
||||||
|
"then": "<b>CSS Tipus 2</b> (mennekes)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2112,13 +2112,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"title": {
|
|
||||||
"mappings": {
|
|
||||||
"1": {
|
|
||||||
"then": "Estació de càrrega per a cotxes"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"climbing": {
|
"climbing": {
|
||||||
|
@ -2643,9 +2636,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Aquesta via ciclista està pavimentada"
|
"then": "Aquesta via ciclista està pavimentada"
|
||||||
},
|
},
|
||||||
"10": {
|
|
||||||
"then": "Aquesta via ciclista està feta de grava fina"
|
|
||||||
},
|
|
||||||
"2": {
|
"2": {
|
||||||
"then": "Aquesta via ciclista està feta d'asfalt"
|
"then": "Aquesta via ciclista està feta d'asfalt"
|
||||||
},
|
},
|
||||||
|
@ -2669,6 +2659,9 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Aquesta via ciclista està feta de grava"
|
"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?",
|
"question": "De quina superfície està fet aquesta via ciclista?",
|
||||||
|
@ -2714,9 +2707,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Aquest carril bici està pavimentat"
|
"then": "Aquest carril bici està pavimentat"
|
||||||
},
|
},
|
||||||
"10": {
|
|
||||||
"then": "Aquesta via ciclista està feta de gravilla"
|
|
||||||
},
|
|
||||||
"2": {
|
"2": {
|
||||||
"then": "Aquest carril bici està fet d'asfalt"
|
"then": "Aquest carril bici està fet d'asfalt"
|
||||||
},
|
},
|
||||||
|
@ -2728,6 +2718,9 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Aquesta via ciclista està feta de grava"
|
"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?",
|
"question": "De què està feta la superfície d'aquest carrer?",
|
||||||
|
@ -3227,8 +3220,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "Aquest ascensor en quins idiomes té sortida de veu?",
|
"question": "Aquest ascensor en quins idiomes té sortida de veu?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Aquest ascensor té sortida de veu en {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3250,8 +3243,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "Aquest ascensor en quins idiomes té l'escriptura tàctil (braille)?",
|
"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_list_item": "Aquest ascensor té l'escriptura tàctil en {language()}",
|
||||||
"render_single_language": "Aquest ascensor té l'escriptura tàctil en {language():font-bold}"
|
"render_single_language": "Aquest ascensor té l'escriptura tàctil en {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3746,21 +3739,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Aquesta estació de fitness té un cartell amb instruccions per a un exercici concret."
|
"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": {
|
"2": {
|
||||||
"then": "Aquesta estació de fitness té una instal·lació per fer abdominals."
|
"then": "Aquesta estació de fitness té una instal·lació per fer abdominals."
|
||||||
},
|
},
|
||||||
|
@ -3784,6 +3762,21 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Aquesta estació de fitness té llocs per fer exercicis d'eslàlom."
|
"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": {
|
"1": {
|
||||||
"then": "Això és una fregiduria"
|
"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": {
|
"2": {
|
||||||
"then": "Principalment serveix pasta"
|
"then": "Principalment serveix pasta"
|
||||||
},
|
},
|
||||||
|
@ -3940,6 +3918,21 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Aquí es serveixen plats francesos"
|
"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í?",
|
"question": "Quin tipus de menjar es serveix aquí?",
|
||||||
|
@ -4492,24 +4485,9 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Açò és un auditori"
|
"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": {
|
"2": {
|
||||||
"then": "Açò és un dormitori"
|
"then": "Açò és un dormitori"
|
||||||
},
|
},
|
||||||
"22": {
|
|
||||||
"then": "Açò és una sala d'espera"
|
|
||||||
},
|
|
||||||
"3": {
|
"3": {
|
||||||
"then": "Açò és una capella"
|
"then": "Açò és una capella"
|
||||||
},
|
},
|
||||||
|
@ -4527,6 +4505,21 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Açò és una cuina"
|
"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?"
|
"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": {
|
"2": {
|
||||||
"options": {
|
"options": {
|
||||||
"0": {
|
"0": {
|
||||||
|
@ -5196,6 +5176,19 @@
|
||||||
"question": "Sols mostra les notes obertes"
|
"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",
|
"name": "Notes d'OpenStreetMap",
|
||||||
|
@ -5495,15 +5488,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Aquesta és una plaça d'aparcament normal."
|
"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": {
|
"2": {
|
||||||
"then": "Aquesta és una plaça d'aparcament per a minusvàlids."
|
"then": "Aquesta és una plaça d'aparcament per a minusvàlids."
|
||||||
},
|
},
|
||||||
|
@ -5521,6 +5505,15 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Es tracta d'una plaça d'aparcament reservada per a motos."
|
"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?"
|
"question": "Quin tipus d'espai d'aparcament és aquest?"
|
||||||
|
@ -6095,21 +6088,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "S'accepten monedes de 2 cèntims"
|
"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": {
|
"2": {
|
||||||
"then": "S'accepten monedes de 5 cèntims"
|
"then": "S'accepten monedes de 5 cèntims"
|
||||||
},
|
},
|
||||||
|
@ -6133,6 +6111,21 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "S'accepten monedes de 10 cèntims"
|
"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í?"
|
"question": "Quines monedes es poden utilitzar per a pagar aquí?"
|
||||||
|
@ -6145,15 +6138,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "S'accepten bitllets de 10 euros"
|
"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": {
|
"2": {
|
||||||
"then": "S'accepten bitllets de 20 euros"
|
"then": "S'accepten bitllets de 20 euros"
|
||||||
},
|
},
|
||||||
|
@ -6177,6 +6161,15 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "S'accepten bitllets de 50 francs"
|
"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í?"
|
"question": "Amb quins bitllets pot pagar aquí?"
|
||||||
|
@ -6531,6 +6524,30 @@
|
||||||
"1": {
|
"1": {
|
||||||
"question": "Reciclatge de piles"
|
"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": {
|
"10": {
|
||||||
"question": "Reciclatge de vidre"
|
"question": "Reciclatge de vidre"
|
||||||
},
|
},
|
||||||
|
@ -6561,35 +6578,11 @@
|
||||||
"19": {
|
"19": {
|
||||||
"question": "Reciclatge del rebuig"
|
"question": "Reciclatge del rebuig"
|
||||||
},
|
},
|
||||||
"2": {
|
|
||||||
"question": "Reciclatge de cartrons de begudes"
|
|
||||||
},
|
|
||||||
"20": {
|
"20": {
|
||||||
"question": "Reciclatge de cartutxos d'impressora"
|
"question": "Reciclatge de cartutxos d'impressora"
|
||||||
},
|
},
|
||||||
"21": {
|
"21": {
|
||||||
"question": "Reciclatge de bicicletes"
|
"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": {
|
"1": {
|
||||||
"then": "Aquí es poden reciclar els cartons de begudes"
|
"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": {
|
"10": {
|
||||||
"then": "Aquí es pot reciclar vidre"
|
"then": "Aquí es pot reciclar vidre"
|
||||||
},
|
},
|
||||||
|
@ -6687,9 +6704,6 @@
|
||||||
"19": {
|
"19": {
|
||||||
"then": "Aquí es poden reciclar sabates"
|
"then": "Aquí es poden reciclar sabates"
|
||||||
},
|
},
|
||||||
"2": {
|
|
||||||
"then": "Aquí es poden reciclar llaunes"
|
|
||||||
},
|
|
||||||
"20": {
|
"20": {
|
||||||
"then": "Aquí es poden reciclar petits electrodomèstics"
|
"then": "Aquí es poden reciclar petits electrodomèstics"
|
||||||
},
|
},
|
||||||
|
@ -6704,27 +6718,6 @@
|
||||||
},
|
},
|
||||||
"24": {
|
"24": {
|
||||||
"then": "Aquí es poden reciclar bicicletes"
|
"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í?"
|
"question": "Què es pot reciclar aquí?"
|
||||||
|
@ -6835,7 +6828,7 @@
|
||||||
"no_known_languages": "La llengua principal d'aquesta escola és desconeguda",
|
"no_known_languages": "La llengua principal d'aquesta escola és desconeguda",
|
||||||
"question": "Quina és la llengua principal d'aquesta escola?<div class='subtle'>Quina llengua es parla amb els estudiants en classes no relacionades amb la llengua i l'administració?</div>",
|
"question": "Quina és la llengua principal d'aquesta escola?<div class='subtle'>Quina llengua es parla amb els estudiants en classes no relacionades amb la llengua i l'administració?</div>",
|
||||||
"render_all": "En aquesta escola s'utilitzen els idiomes següents:{list()}",
|
"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": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "En quins idiomes hi ha escriptura tàctil (braille) per a la navegació? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
"question": "En quins idiomes hi ha escriptura tàctil (braille) per a la navegació? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Aquestes escales tenen escriptura tàctil en {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7472,12 +7465,6 @@
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Aquest fanal utilitza LED"
|
"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": {
|
"2": {
|
||||||
"then": "Aquest fanal utilitza il·luminació incandescent"
|
"then": "Aquest fanal utilitza il·luminació incandescent"
|
||||||
},
|
},
|
||||||
|
@ -7501,6 +7488,12 @@
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"then": "Aquest fanal utilitza làmpades de sodi de baixa pressió (taronja monocroma)"
|
"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?"
|
"question": "Quin tipus d'il·luminació utilitza aquest fanal?"
|
||||||
|
@ -8705,6 +8698,30 @@
|
||||||
"1": {
|
"1": {
|
||||||
"question": "Venda de begudes"
|
"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": {
|
"10": {
|
||||||
"question": "Venda de llet"
|
"question": "Venda de llet"
|
||||||
},
|
},
|
||||||
|
@ -8735,9 +8752,6 @@
|
||||||
"19": {
|
"19": {
|
||||||
"question": "Venda de flors"
|
"question": "Venda de flors"
|
||||||
},
|
},
|
||||||
"2": {
|
|
||||||
"question": "Venda de llaminadures"
|
|
||||||
},
|
|
||||||
"20": {
|
"20": {
|
||||||
"question": "Venda de tiquets d'aparcament"
|
"question": "Venda de tiquets d'aparcament"
|
||||||
},
|
},
|
||||||
|
@ -8761,27 +8775,6 @@
|
||||||
},
|
},
|
||||||
"27": {
|
"27": {
|
||||||
"question": "Venda de cadenat per a bicicletes"
|
"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": {
|
"1": {
|
||||||
"then": "Es venen llaminadures"
|
"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": {
|
"10": {
|
||||||
"then": "Es ven pa"
|
"then": "Es ven pa"
|
||||||
},
|
},
|
||||||
|
@ -8858,9 +8875,6 @@
|
||||||
"19": {
|
"19": {
|
||||||
"then": "Es venen tiquets d'aparcament"
|
"then": "Es venen tiquets d'aparcament"
|
||||||
},
|
},
|
||||||
"2": {
|
|
||||||
"then": "Es ven menjar"
|
|
||||||
},
|
|
||||||
"20": {
|
"20": {
|
||||||
"then": "Es venen cèntims premsats"
|
"then": "Es venen cèntims premsats"
|
||||||
},
|
},
|
||||||
|
@ -8881,27 +8895,6 @@
|
||||||
},
|
},
|
||||||
"26": {
|
"26": {
|
||||||
"then": "Es venen cadenats per a bicicletes"
|
"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?",
|
"question": "Que ven aquesta màquina expenedora?",
|
||||||
|
@ -9193,4 +9186,4 @@
|
||||||
"render": "Turbina eòlica"
|
"render": "Turbina eòlica"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -489,8 +489,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "V jakých jazycích má tento bankomat řečový výstup?",
|
"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_list_item": "Tento bankomat má řečový výstup v {language()}",
|
||||||
"render_single_language": "Tento bankomat má řečový výstup v {language():font-bold}"
|
"render_single_language": "Tento bankomat má řečový výstup v {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3269,8 +3269,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "Ve kterých jazycích má tento výtah hlasový výstup?",
|
"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_list_item": "Tento výtah má hlasový výstup v {language()}",
|
||||||
"render_single_language": "Tento výtah má hlasový výstup v {language():font-bold}"
|
"render_single_language": "Tento výtah má hlasový výstup v {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3301,8 +3301,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "Ve kterých jazycích má tento výtah hmatové písmo (braillovo písmo)?",
|
"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_list_item": "Tento výtah má hmatové písmo v {language()}",
|
||||||
"render_single_language": "Tento výtah má hmatové písmo v {language():font-bold}"
|
"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",
|
"no_known_languages": "Hlavní jazyk této školy není znám",
|
||||||
"question": "Jaký je hlavní jazyk této školy?<div class='subtle'>Jakým jazykem se mluví se studenty v nejazykových kurzech a administrativou?</div>",
|
"question": "Jaký je hlavní jazyk této školy?<div class='subtle'>Jakým jazykem se mluví se studenty v nejazykových kurzech a administrativou?</div>",
|
||||||
"render_all": "V této škole se používají následující jazyky:{list()}",
|
"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": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "Ve kterých jazycích existuje hmatové písmo (braillské písmo) pro navigaci? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
"question": "Ve kterých jazycích existuje hmatové písmo (braillské písmo) pro navigaci? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Tyto schody mají hmatové písmo v {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -530,8 +530,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In welchen Sprachen hat dieser Geldautomat eine Sprachausgabe?",
|
"question": "In welchen Sprachen hat dieser Geldautomat eine Sprachausgabe?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Dieser Geldautomat hat eine Sprachausgabe in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3859,8 +3859,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In welchen Sprachen verfügt der Aufzug über eine Sprachausgabe?",
|
"question": "In welchen Sprachen verfügt der Aufzug über eine Sprachausgabe?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Der Aufzug hat eine Sprachausgabe in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3891,8 +3891,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In welchen Sprachen hat der Aufzug taktile Schrift (Braille)?",
|
"question": "In welchen Sprachen hat der Aufzug taktile Schrift (Braille)?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Der Aufzug hat taktile Schrift in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7949,7 +7949,7 @@
|
||||||
"no_known_languages": "Die Unterrichtssprache der Schule ist unbekannt",
|
"no_known_languages": "Die Unterrichtssprache der Schule ist unbekannt",
|
||||||
"question": "Was ist die Hauptsprache dieser Schule?<div class='subtle'>Welche Sprache wird mit den Schülern in den nicht sprachbezogenen Kursen und mit der Verwaltung gesprochen?</div>",
|
"question": "Was ist die Hauptsprache dieser Schule?<div class='subtle'>Welche Sprache wird mit den Schülern in den nicht sprachbezogenen Kursen und mit der Verwaltung gesprochen?</div>",
|
||||||
"render_all": "Folgende Sprachen werden in der Schule verwendet:{list()}",
|
"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": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In welchen Sprachen gibt es taktile Schrift (Braille) für die Navigation? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
"question": "In welchen Sprachen gibt es taktile Schrift (Braille) für die Navigation? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Die Treppe hat taktile Schrift in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -530,8 +530,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In which languages does this ATM have speech output?",
|
"question": "In which languages does this ATM have speech output?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "This ATM has speech output in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1809,6 +1809,24 @@
|
||||||
"render": "Bird watching place"
|
"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 <b>{name}</b>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"render": "Brothel"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cafe_pub": {
|
"cafe_pub": {
|
||||||
"deletion": {
|
"deletion": {
|
||||||
"extraDeleteReasons": {
|
"extraDeleteReasons": {
|
||||||
|
@ -2385,6 +2403,26 @@
|
||||||
"render": "Charging station"
|
"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": {
|
"climbing": {
|
||||||
"description": "A dummy layer which contains tagrenderings, shared among the climbing layers",
|
"description": "A dummy layer which contains tagrenderings, shared among the climbing layers",
|
||||||
"tagRenderings": {
|
"tagRenderings": {
|
||||||
|
@ -3859,8 +3897,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In which languages does this elevator have speech output?",
|
"question": "In which languages does this elevator have speech output?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "This elevator has speech output in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3891,8 +3929,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In which languages does this elevator have tactile writing (braille)?",
|
"question": "In which languages does this elevator have tactile writing (braille)?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "This elevator has tactile writing in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5024,6 +5062,9 @@
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"then": "There is no {negative-name} available at this hackerspace"
|
"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?"
|
"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 <b>{name}</b>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"render": "Love Hotel <i>{name}</i>"
|
||||||
|
}
|
||||||
|
},
|
||||||
"map": {
|
"map": {
|
||||||
"description": "A map, meant for tourists which is permanently installed in the public space",
|
"description": "A map, meant for tourists which is permanently installed in the public space",
|
||||||
"name": "Maps",
|
"name": "Maps",
|
||||||
|
@ -7949,7 +8009,7 @@
|
||||||
"no_known_languages": "The main language of this school is unknown",
|
"no_known_languages": "The main language of this school is unknown",
|
||||||
"question": "What is the main language of this school?<div class='subtle'>What language is spoken with the students in non-language related courses and with the administration?</div>",
|
"question": "What is the main language of this school?<div class='subtle'>What language is spoken with the students in non-language related courses and with the administration?</div>",
|
||||||
"render_all": "The following languages are used in this school:{list()}",
|
"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": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In which languages is there tactile writing (braille) for navigation? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
"question": "In which languages is there tactile writing (braille) for navigation? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "These stairs have tactile writing in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8784,6 +8844,24 @@
|
||||||
"render": "Street Lamp"
|
"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 <b>{name}</b>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"render": "Stripclub"
|
||||||
|
}
|
||||||
|
},
|
||||||
"surveillance_camera": {
|
"surveillance_camera": {
|
||||||
"description": "This layer shows surveillance cameras and allows a contributor to update information and add new cameras",
|
"description": "This layer shows surveillance cameras and allows a contributor to update information and add new cameras",
|
||||||
"name": "Surveillance camera's",
|
"name": "Surveillance camera's",
|
||||||
|
|
|
@ -530,8 +530,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "¿En qué idiomas tiene salida de voz este cajero automático?",
|
"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_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():font-bold}"
|
"render_single_language": "Este cajero automático tiene salida de voz en {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5232,7 +5232,7 @@
|
||||||
"no_known_languages": "La langue principale de cette école est inconnue",
|
"no_known_languages": "La langue principale de cette école est inconnue",
|
||||||
"question": "Quelle est la langue principale de cette école ?<div class='subtle'>Quelle langue est parlée avec les élèves des cours non linguistiques et avec l'administration ?</div>",
|
"question": "Quelle est la langue principale de cette école ?<div class='subtle'>Quelle langue est parlée avec les élèves des cours non linguistiques et avec l'administration ?</div>",
|
||||||
"render_all": "Ces langues sont utilisées dans cette école :{list()}",
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -281,8 +281,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "באילו שפות יש לכספומט הזה פלט דיבור?",
|
"question": "באילו שפות יש לכספומט הזה פלט דיבור?",
|
||||||
"render_list_item": "לכספומט הזה יש פלט דיבור ב {language():font-bold}",
|
"render_list_item": "לכספומט הזה יש פלט דיבור ב {language()}",
|
||||||
"render_single_language": "לכספומט הזה יש פלט דיבור ב {language():font-bold}"
|
"render_single_language": "לכספומט הזה יש פלט דיבור ב {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,8 +385,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In welke taal is de spraak van deze geldautomaat?",
|
"question": "In welke taal is de spraak van deze geldautomaat?",
|
||||||
"render_list_item": "Deze geldautomaat heeft spraak in {language():font-bold}",
|
"render_list_item": "Deze geldautomaat heeft spraak in {language()}",
|
||||||
"render_single_language": "Deze automaat heeft spraak in {language():font-bold}"
|
"render_single_language": "Deze automaat heeft spraak in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3684,8 +3684,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In welke talen heeft deze lift gesproken tekst?",
|
"question": "In welke talen heeft deze lift gesproken tekst?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Deze lift heeft gesproken tekst in het {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3693,8 +3693,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In welke talen heeft deze lift voelbaar schrift (braille)?",
|
"question": "In welke talen heeft deze lift voelbaar schrift (braille)?",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Deze lift heeft voelbaar schrift in het {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4498,6 +4498,9 @@
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"then": "Er is geen {negative-name} beschikbaar in deze hackerspace"
|
"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?"
|
"question": "Is er {device-name} beschikbaar in deze hackerspace?"
|
||||||
|
@ -7533,8 +7536,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "In welke talen is er voelbaar schrift (braille) voor navigatie? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
"question": "In welke talen is er voelbaar schrift (braille) voor navigatie? <img src='./assets/layers/stairs/Braille_stairs.jpg' style='height: 300px; width: auto; display: block;' />",
|
||||||
"render_list_item": "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():font-bold}"
|
"render_single_language": "Deze trap heeft voelbaar schrijft in {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2604,7 +2604,7 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"render_all": "Następujące języki są używane w tej szkole:{list()}",
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -500,7 +500,7 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "Em que línguas este multibanco tem saída de fala?",
|
"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()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -489,8 +489,8 @@
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"question": "Em quais línguas esse caixa eletrônico tem saída de fala?",
|
"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_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():font-bold}"
|
"render_single_language": "Este caixa eletrônico tem saída de fala em {language()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -868,111 +868,6 @@
|
||||||
},
|
},
|
||||||
"title": "Vorals i encreuaments"
|
"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": "<b>No</b> 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 <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>"
|
|
||||||
},
|
|
||||||
"host": {
|
|
||||||
"question": "Amb quin amfitrió (lloc web) es va fer aquest canvi?",
|
|
||||||
"render": "Canviat amb <a href='{host}'>{host}</a>"
|
|
||||||
},
|
|
||||||
"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 <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
|
|
||||||
},
|
|
||||||
"theme-id": {
|
|
||||||
"question": "Quin tema es va utilitzar per fer aquest canvi?",
|
|
||||||
"render": "Canvi amb el tema <a href='https://mapcomplete.org/{theme}'>{theme}</a>"
|
|
||||||
},
|
|
||||||
"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 <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>aquí</a>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shortDescription": "Mostra els canvis fets amb MapComplete",
|
|
||||||
"title": "Canvis fets amb MapComplete"
|
|
||||||
},
|
|
||||||
"maproulette": {
|
"maproulette": {
|
||||||
"description": "Tema que mostra les tasques de MapRoulette, que us permet cercar-les, filtrar-les i solucionar-les.",
|
"description": "Tema que mostra les tasques de MapRoulette, que us permet cercar-les, filtrar-les i solucionar-les.",
|
||||||
"title": "Tasques de MapRoulette"
|
"title": "Tasques de MapRoulette"
|
||||||
|
|
|
@ -898,133 +898,6 @@
|
||||||
},
|
},
|
||||||
"title": "Bordsteine und Überwege"
|
"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 <b>nicht</b> {search}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
"options": {
|
|
||||||
"0": {
|
|
||||||
"question": "Der Name enthält <b>nicht</b> {search}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"3": {
|
|
||||||
"options": {
|
|
||||||
"0": {
|
|
||||||
"question": "<b>Nicht</b> 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 <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>"
|
|
||||||
},
|
|
||||||
"host": {
|
|
||||||
"question": "Über welchen Host (Webseite) wurde diese Änderung vorgenommen?",
|
|
||||||
"render": "Geändert über <a href='{host}'>{host}</a>"
|
|
||||||
},
|
|
||||||
"locale": {
|
|
||||||
"question": "In welcher Benutzersprache wurde diese Änderung vorgenommen?",
|
|
||||||
"render": "Benutzersprache {locale}"
|
|
||||||
},
|
|
||||||
"show_changeset_id": {
|
|
||||||
"render": "Änderungssatz <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
|
|
||||||
},
|
|
||||||
"theme-id": {
|
|
||||||
"question": "Welches Theme wurde für diese Änderung verwendet?",
|
|
||||||
"render": "Geändert mit Thema <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>"
|
|
||||||
},
|
|
||||||
"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 <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>hier</a>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shortDescription": "Zeigt die von MapComplete vorgenommenen Änderungen an",
|
|
||||||
"title": "Mit MapComplete vorgenommene Änderungen"
|
|
||||||
},
|
|
||||||
"maproulette": {
|
"maproulette": {
|
||||||
"description": "Thema mit MapRoulette-Aufgaben, die Sie suchen, filtern und beheben können.",
|
"description": "Thema mit MapRoulette-Aufgaben, die Sie suchen, filtern und beheben können.",
|
||||||
"title": "MapRoulette-Aufgaben"
|
"title": "MapRoulette-Aufgaben"
|
||||||
|
|
|
@ -1129,6 +1129,57 @@
|
||||||
},
|
},
|
||||||
"title": "OnWheels"
|
"title": "OnWheels"
|
||||||
},
|
},
|
||||||
|
"openlovemap": {
|
||||||
|
"description": "<p><i>Love in the palm of your hand</i></p>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": {
|
"openwindpowermap": {
|
||||||
"description": "A map for showing and editing wind turbines.",
|
"description": "A map for showing and editing wind turbines.",
|
||||||
"title": "Wind power generators"
|
"title": "Wind power generators"
|
||||||
|
|
|
@ -898,23 +898,6 @@
|
||||||
},
|
},
|
||||||
"title": "Bordillos y cruces"
|
"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": {
|
"maproulette": {
|
||||||
"description": "Tema que muestra las tareas de MapRoulette, permitiendo buscarlas, filtrarlas y arreglarlas.",
|
"description": "Tema que muestra las tareas de MapRoulette, permitiendo buscarlas, filtrarlas y arreglarlas.",
|
||||||
"title": "Tareas de MapRoulette"
|
"title": "Tareas de MapRoulette"
|
||||||
|
|
|
@ -103,7 +103,7 @@ export default class OverpassFeatureSource implements FeatureSource {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const [bounds, _, _] = result
|
const [bounds, _, __] = result
|
||||||
this._lastQueryBBox = bounds
|
this._lastQueryBBox = bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`
|
||||||
|
|
|
@ -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<boolean> {
|
|
||||||
public readonly _selected: UIEventSource<boolean>
|
|
||||||
public readonly isShown: Store<boolean> = new UIEventSource<boolean>(true)
|
|
||||||
public readonly matchesSearchCriteria: Store<boolean>
|
|
||||||
public readonly forceSelected: UIEventSource<boolean>
|
|
||||||
private readonly _shown: BaseUIElement
|
|
||||||
private readonly _squared: boolean
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
shown: string | BaseUIElement,
|
|
||||||
mainTerm: Record<string, string>,
|
|
||||||
search: Store<string>,
|
|
||||||
options?: {
|
|
||||||
searchTerms?: Record<string, string[]>
|
|
||||||
selected?: UIEventSource<boolean>
|
|
||||||
forceSelected?: UIEventSource<boolean>
|
|
||||||
squared?: boolean
|
|
||||||
/* Hide, if not selected*/
|
|
||||||
hide?: Store<boolean>
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
super()
|
|
||||||
this._shown = Translations.W(shown)
|
|
||||||
this._squared = options?.squared ?? false
|
|
||||||
const searchTerms: Record<string, string[]> = {}
|
|
||||||
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<boolean>(false))
|
|
||||||
const forceSelected = (this.forceSelected =
|
|
||||||
options?.forceSelected ?? new UIEventSource<boolean>(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<boolean> {
|
|
||||||
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<T> extends Combine implements InputElement<T[]> {
|
|
||||||
public readonly someMatchFound: Store<boolean>
|
|
||||||
private readonly selectedElements: UIEventSource<T[]>
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param values: the values that can be selected
|
|
||||||
* @param options
|
|
||||||
*/
|
|
||||||
constructor(
|
|
||||||
values: {
|
|
||||||
show: BaseUIElement
|
|
||||||
value: T
|
|
||||||
mainTerm: Record<string, string>
|
|
||||||
searchTerms?: Record<string, string[]>
|
|
||||||
/* If there are more then 200 elements, should this element still be shown? */
|
|
||||||
hasPriority?: Store<boolean>
|
|
||||||
}[],
|
|
||||||
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<T[]>
|
|
||||||
/**
|
|
||||||
* The search bar. Use this to seed the search value or to tie to another value
|
|
||||||
*/
|
|
||||||
searchValue?: UIEventSource<string>
|
|
||||||
/**
|
|
||||||
* 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<T[]>([])
|
|
||||||
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<string, string>
|
|
||||||
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<number>
|
|
||||||
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<T[]> {
|
|
||||||
return this.selectedElements
|
|
||||||
}
|
|
||||||
|
|
||||||
IsValid(_: T[]): boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<string> {
|
|
||||||
constructor(options?: {
|
|
||||||
mode?: "select-many" | "select-one"
|
|
||||||
currentCountry?: Store<string>
|
|
||||||
supportedLanguages?: Record<string, string> & { _meta?: { countries?: string[] } }
|
|
||||||
}) {
|
|
||||||
const possibleValues: {
|
|
||||||
show: BaseUIElement
|
|
||||||
value: string
|
|
||||||
mainTerm: Record<string, string>
|
|
||||||
searchTerms?: Record<string, string[]>
|
|
||||||
hasPriority?: Store<boolean>
|
|
||||||
}[] = []
|
|
||||||
|
|
||||||
const langs = options?.supportedLanguages ?? all_languages
|
|
||||||
for (const ln in langs) {
|
|
||||||
let languageInfo: Record<string, string> & { _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",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<Record<string, string>>,
|
|
||||||
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<string, BaseUIElement>()
|
|
||||||
mapping.set("language", new Translation(all_languages[ln]))
|
|
||||||
rendered = new SubstitutedTranslation(
|
|
||||||
new Translation({ "*": single_render }, undefined),
|
|
||||||
tagSource,
|
|
||||||
state,
|
|
||||||
mapping
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let mapping = new Map<string, BaseUIElement>()
|
|
||||||
const languagesList = new List(
|
|
||||||
foundLanguages.map((ln) => {
|
|
||||||
let mappingLn = new Map<string, BaseUIElement>()
|
|
||||||
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]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
46
src/UI/Popup/LanguageElement/LanguageAnswer.svelte
Normal file
46
src/UI/Popup/LanguageElement/LanguageAnswer.svelte
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Store, UIEventSource } from "../../../Logic/UIEventSource"
|
||||||
|
import SpecialTranslation from "../TagRendering/SpecialTranslation.svelte"
|
||||||
|
import { Translation, TypedTranslation } from "../../i18n/Translation"
|
||||||
|
import type { SpecialVisualizationState } from "../../SpecialVisualization"
|
||||||
|
import type { Feature } from "geojson"
|
||||||
|
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||||
|
import * as all_languages from "../../../assets/language_translations.json"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visualizes a list of the known languages
|
||||||
|
*/
|
||||||
|
export let languages: Store<string[]>
|
||||||
|
export let single_render: string
|
||||||
|
export let item_render: string
|
||||||
|
export let render_all: string // Should contain one `{list()}`
|
||||||
|
|
||||||
|
export let tags: UIEventSource<Record<string, string>>
|
||||||
|
|
||||||
|
export let state: SpecialVisualizationState
|
||||||
|
export let feature: Feature
|
||||||
|
export let layer: LayerConfig | undefined
|
||||||
|
|
||||||
|
let [beforeListing, afterListing] = (render_all ?? "{list()}").split("{list()}")
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $languages.length === 1}
|
||||||
|
<SpecialTranslation {state} {tags} {feature} {layer}
|
||||||
|
t={new TypedTranslation({"*": single_render}).PartialSubsTr(
|
||||||
|
"language()",
|
||||||
|
new Translation(all_languages[$languages[0]], undefined)
|
||||||
|
)}/>
|
||||||
|
{:else}
|
||||||
|
{beforeListing}
|
||||||
|
<ul>
|
||||||
|
{#each $languages as language}
|
||||||
|
<li>
|
||||||
|
<SpecialTranslation {state} {tags} {feature} {layer} t={
|
||||||
|
new TypedTranslation({"*": item_render}).PartialSubsTr("language()",
|
||||||
|
new Translation(all_languages[language], undefined) )}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
{afterListing}
|
||||||
|
{/if}
|
69
src/UI/Popup/LanguageElement/LanguageElement.svelte
Normal file
69
src/UI/Popup/LanguageElement/LanguageElement.svelte
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { UIEventSource } from "../../../Logic/UIEventSource"
|
||||||
|
import LanguageQuestion from "./LanguageQuestion.svelte"
|
||||||
|
import LanguageAnswer from "./LanguageAnswer.svelte"
|
||||||
|
import Tr from "../../Base/Tr.svelte"
|
||||||
|
import Translations from "../../i18n/Translations"
|
||||||
|
import type { SpecialVisualizationState } from "../../SpecialVisualization"
|
||||||
|
import type { Feature } from "geojson"
|
||||||
|
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||||
|
import EditButton from "../TagRendering/EditButton.svelte"
|
||||||
|
|
||||||
|
export let key: string
|
||||||
|
export let tags: UIEventSource<Record<string, string>>
|
||||||
|
|
||||||
|
export let state: SpecialVisualizationState
|
||||||
|
export let feature: Feature
|
||||||
|
export let layer: LayerConfig | undefined
|
||||||
|
|
||||||
|
export let question: string
|
||||||
|
export let on_no_known_languages: string = undefined
|
||||||
|
export let single_render: string
|
||||||
|
export let item_render: string
|
||||||
|
export let render_all: string // Should contain one `{list()}`
|
||||||
|
let prefix = key + ":"
|
||||||
|
let foundLanguages = tags.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)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $foundLanguages.length === 0 && on_no_known_languages && !$forceInputMode}
|
||||||
|
<div class="p-1 flex items-center justify-between low-interaction rounded">
|
||||||
|
<div>
|
||||||
|
{on_no_known_languages}
|
||||||
|
</div>
|
||||||
|
<EditButton on:click={_ => forceInputMode.setData(true)} />
|
||||||
|
</div>
|
||||||
|
{:else if $forceInputMode || $foundLanguages.length === 0}
|
||||||
|
<LanguageQuestion {question} {foundLanguages} {prefix} {state} {tags} {feature} {layer}
|
||||||
|
on:save={_ => forceInputMode.setData(false)}>
|
||||||
|
<span slot="cancel-button">
|
||||||
|
{#if $forceInputMode}
|
||||||
|
<button on:click={_ => forceInputMode.setData(false)}>
|
||||||
|
<Tr t={Translations.t.general.cancel} />
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</LanguageQuestion>
|
||||||
|
{:else}
|
||||||
|
<div class="p-2 flex items-center justify-between low-interaction rounded">
|
||||||
|
<div>
|
||||||
|
<LanguageAnswer {single_render} {item_render} {render_all} languages={foundLanguages} {state} {tags} { feature}
|
||||||
|
{layer} />
|
||||||
|
</div>
|
||||||
|
<EditButton on:click={_ => forceInputMode.setData(true)} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
107
src/UI/Popup/LanguageElement/LanguageElement.ts
Normal file
107
src/UI/Popup/LanguageElement/LanguageElement.ts
Normal file
|
@ -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<Record<string, string>>,
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
133
src/UI/Popup/LanguageElement/LanguageOptions.svelte
Normal file
133
src/UI/Popup/LanguageElement/LanguageOptions.svelte
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
<script lang="ts">/**
|
||||||
|
* An input element which allows to select one or more langauges
|
||||||
|
*/
|
||||||
|
import { UIEventSource } from "../../../Logic/UIEventSource"
|
||||||
|
import all_languages from "../../../assets/language_translations.json"
|
||||||
|
import { Translation } from "../../i18n/Translation"
|
||||||
|
import Tr from "../../Base/Tr.svelte"
|
||||||
|
import Translations from "../../i18n/Translations.js"
|
||||||
|
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||||
|
import Locale from "../../i18n/Locale"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will contain one or more ISO-language codes
|
||||||
|
*/
|
||||||
|
export let selectedLanguages: UIEventSource<string[]>
|
||||||
|
/**
|
||||||
|
* The country (countries) that the point lies in.
|
||||||
|
* Note that a single place might be claimed by multiple countries
|
||||||
|
*/
|
||||||
|
export let countries: Set<string>
|
||||||
|
let searchValue: UIEventSource<string> = new UIEventSource<string>("")
|
||||||
|
let searchLC = searchValue.mapD(search => search.toLowerCase())
|
||||||
|
const knownLanguagecodes = Object.keys(all_languages)
|
||||||
|
let probableLanguages = []
|
||||||
|
let isChecked = {}
|
||||||
|
for (const lng of knownLanguagecodes) {
|
||||||
|
const lngInfo = all_languages[lng]
|
||||||
|
if (lngInfo._meta?.countries?.some(l => countries.has(l))) {
|
||||||
|
probableLanguages.push(lng)
|
||||||
|
}
|
||||||
|
isChecked[lng] = false
|
||||||
|
}
|
||||||
|
let newlyChecked: UIEventSource<string[]> = new UIEventSource<string[]>([])
|
||||||
|
|
||||||
|
function update(isChecked: Record<string, boolean>) {
|
||||||
|
const currentlyChecked = new Set<string>(selectedLanguages.data)
|
||||||
|
const languages: string[] = []
|
||||||
|
for (const lng in isChecked) {
|
||||||
|
if (isChecked[lng]) {
|
||||||
|
languages.push(lng)
|
||||||
|
if (!currentlyChecked.has(lng)) {
|
||||||
|
newlyChecked.data.push(lng)
|
||||||
|
newlyChecked.ping()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedLanguages.setData(languages)
|
||||||
|
}
|
||||||
|
function matchesSearch(lng: string, searchLc: string | undefined): boolean {
|
||||||
|
if(!searchLc){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(lng.indexOf(searchLc) >= 0){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const languageInfo = all_languages[lng]
|
||||||
|
const native : string = languageInfo[lng]?.toLowerCase()
|
||||||
|
if(native?.indexOf(searchLc) >= 0){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const current : string = languageInfo[Locale.language.data]?.toLowerCase()
|
||||||
|
if(current?.indexOf(searchLc) >= 0){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
function onEnter(){
|
||||||
|
// we select the first match which is not yet checked
|
||||||
|
for (const lng of knownLanguagecodes) {
|
||||||
|
if(lng === searchLC.data){
|
||||||
|
isChecked[lng] = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const lng of knownLanguagecodes) {
|
||||||
|
if(matchesSearch(lng, searchLC.data)){
|
||||||
|
isChecked[lng] = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$: {
|
||||||
|
update(isChecked)
|
||||||
|
}
|
||||||
|
searchValue.addCallback(_ => {
|
||||||
|
newlyChecked.setData([])
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<form on:submit|preventDefault={() => onEnter()}>
|
||||||
|
|
||||||
|
{#each probableLanguages as lng}
|
||||||
|
|
||||||
|
<label class="no-image-background flex items-center gap-1">
|
||||||
|
<input bind:checked={isChecked[lng]} type="checkbox" />
|
||||||
|
<Tr t={new Translation(all_languages[lng])} />
|
||||||
|
<span class="subtle">({lng})</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<label class="block relative neutral-label m-4 mx-16">
|
||||||
|
<SearchIcon class="w-6 h-6 absolute right-0" />
|
||||||
|
<input bind:value={$searchValue} type="text" />
|
||||||
|
<Tr t={Translations.t.general.useSearch} />
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="overflow-auto" style="max-height: 25vh">
|
||||||
|
{#each knownLanguagecodes as lng}
|
||||||
|
{#if (isChecked[lng]) && $newlyChecked.indexOf(lng) < 0 && probableLanguages.indexOf(lng) < 0}
|
||||||
|
<label class="no-image-background flex items-center gap-1">
|
||||||
|
<input bind:checked={isChecked[lng]} type="checkbox" />
|
||||||
|
<Tr t={new Translation(all_languages[lng])} />
|
||||||
|
<span class="subtle">({lng})</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
{#each knownLanguagecodes as lng}
|
||||||
|
{#if $searchLC.length > 0 && matchesSearch(lng, $searchLC) && (!isChecked[lng] || $newlyChecked.indexOf(lng) >= 0) && probableLanguages.indexOf(lng) < 0}
|
||||||
|
<label class="no-image-background flex items-center gap-1">
|
||||||
|
<input bind:checked={isChecked[lng]} type="checkbox" />
|
||||||
|
<Tr t={new Translation(all_languages[lng])} />
|
||||||
|
<span class="subtle">({lng})</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</form>
|
87
src/UI/Popup/LanguageElement/LanguageQuestion.svelte
Normal file
87
src/UI/Popup/LanguageElement/LanguageQuestion.svelte
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<script lang="ts">/**
|
||||||
|
* The 'languageQuestion' is a special element which asks about the (possible) languages of a feature
|
||||||
|
* (e.g. which speech output an ATM has, in what language(s) the braille writing is or what languages are spoken at a school)
|
||||||
|
*
|
||||||
|
* This is written into a `key`.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
import { Translation } from "../../i18n/Translation"
|
||||||
|
import SpecialTranslation from "../TagRendering/SpecialTranslation.svelte"
|
||||||
|
import type { SpecialVisualizationState } from "../../SpecialVisualization"
|
||||||
|
import type { Store } from "../../../Logic/UIEventSource"
|
||||||
|
import { UIEventSource } from "../../../Logic/UIEventSource"
|
||||||
|
|
||||||
|
import type { Feature } from "geojson"
|
||||||
|
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||||
|
import LanguageOptions from "./LanguageOptions.svelte"
|
||||||
|
import Translations from "../../i18n/Translations"
|
||||||
|
import Tr from "../../Base/Tr.svelte"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
import { Tag } from "../../../Logic/Tags/Tag"
|
||||||
|
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction"
|
||||||
|
import { And } from "../../../Logic/Tags/And"
|
||||||
|
|
||||||
|
export let question: string
|
||||||
|
export let prefix: string
|
||||||
|
|
||||||
|
export let foundLanguages: Store<string[]>
|
||||||
|
export let state: SpecialVisualizationState
|
||||||
|
export let tags: UIEventSource<Record<string, string>>
|
||||||
|
export let feature: Feature
|
||||||
|
export let layer: LayerConfig | undefined
|
||||||
|
let dispatch = createEventDispatcher<{ save }>()
|
||||||
|
|
||||||
|
let selectedLanguages: UIEventSource<string[]> = new UIEventSource<string[]>([])
|
||||||
|
let countries: Store<Set<string>> = tags.mapD(tags => new Set<string>(tags["_country"]?.toUpperCase()?.split(";") ?? []))
|
||||||
|
async function applySelectedLanguages() {
|
||||||
|
const selectedLngs = selectedLanguages.data
|
||||||
|
const selection: Tag[] = selectedLanguages.data.map((ln) => new Tag(prefix + ln, "yes"))
|
||||||
|
if (selection.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const currentLanguages = foundLanguages.data
|
||||||
|
|
||||||
|
for (const currentLanguage of currentLanguages) {
|
||||||
|
if (selectedLngs.indexOf(currentLanguage) >= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Erase languages that are not spoken anymore
|
||||||
|
selection.push(new Tag(prefix + currentLanguage, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state === undefined || state?.featureSwitchIsTesting?.data) {
|
||||||
|
for (const tag of selection) {
|
||||||
|
tags.data[tag.key] = tag.value
|
||||||
|
}
|
||||||
|
tags.ping()
|
||||||
|
} else if (state.changes) {
|
||||||
|
await state.changes
|
||||||
|
.applyAction(
|
||||||
|
new ChangeTagAction(
|
||||||
|
tags.data.id,
|
||||||
|
new And(selection),
|
||||||
|
tags.data,
|
||||||
|
{
|
||||||
|
theme: state?.layout?.id ?? "unkown",
|
||||||
|
changeType: "answer",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
dispatch("save")
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col disable-links interactive border-interactive p-2">
|
||||||
|
<div class="interactive justify-between pt-1 font-bold">
|
||||||
|
<SpecialTranslation {feature} {layer} {state} t={new Translation({"*":question})} {tags} />
|
||||||
|
</div>
|
||||||
|
<LanguageOptions {selectedLanguages} countries={$countries}/>
|
||||||
|
|
||||||
|
<div class="flex justify-end flex-wrap-reverse w-full">
|
||||||
|
<slot name="cancel-button"></slot>
|
||||||
|
<button class="primary" class:disabled={$selectedLanguages.length === 0} on:click={_ => applySelectedLanguages()}>
|
||||||
|
<Tr t={Translations.t.general.save} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -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<any>,
|
|
||||||
state: {
|
|
||||||
readonly osmConnection?: OsmConnection
|
|
||||||
readonly featureSwitchUserbadge?: Store<boolean>
|
|
||||||
},
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
23
src/UI/Popup/TagRendering/EditButton.svelte
Normal file
23
src/UI/Popup/TagRendering/EditButton.svelte
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { PencilAltIcon } from "@rgossiaux/svelte-heroicons/solid";
|
||||||
|
import { ariaLabel } from "../../../Utils/ariaLabel.js";
|
||||||
|
import { Translation } from "../../i18n/Translation"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A small, round button with an edit-icon (and aria-labels etc)
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* What arialabel to apply onto this button?
|
||||||
|
*/
|
||||||
|
export let arialabel : Translation = undefined;
|
||||||
|
export let ariaLabelledBy: string = undefined
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button
|
||||||
|
on:click
|
||||||
|
class="secondary h-8 w-8 shrink-0 self-start rounded-full p-1"
|
||||||
|
aria-labelledby={arialabel === undefined ? ariaLabelledBy : undefined}
|
||||||
|
use:ariaLabel={arialabel}
|
||||||
|
>
|
||||||
|
<PencilAltIcon />
|
||||||
|
</button>
|
|
@ -13,6 +13,8 @@
|
||||||
import { Utils } from "../../../Utils"
|
import { Utils } from "../../../Utils"
|
||||||
import { twMerge } from "tailwind-merge"
|
import { twMerge } from "tailwind-merge"
|
||||||
import { ariaLabel } from "../../../Utils/ariaLabel"
|
import { ariaLabel } from "../../../Utils/ariaLabel"
|
||||||
|
import EditButton from "./EditButton.svelte"
|
||||||
|
import EditItemButton from "../../Studio/EditItemButton.svelte"
|
||||||
|
|
||||||
export let config: TagRenderingConfig
|
export let config: TagRenderingConfig
|
||||||
export let tags: UIEventSource<Record<string, string>>
|
export let tags: UIEventSource<Record<string, string>>
|
||||||
|
@ -102,16 +104,12 @@
|
||||||
{:else}
|
{:else}
|
||||||
<div class="low-interaction flex items-center justify-between overflow-hidden rounded px-2">
|
<div class="low-interaction flex items-center justify-between overflow-hidden rounded px-2">
|
||||||
<TagRenderingAnswer id={answerId} {config} {tags} {selectedElement} {state} {layer} />
|
<TagRenderingAnswer id={answerId} {config} {tags} {selectedElement} {state} {layer} />
|
||||||
<button
|
<EditButton
|
||||||
|
arialabel={config.editButtonAriaLabel}
|
||||||
|
ariaLabelledBy={answerId}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
editMode = true
|
editMode = true
|
||||||
}}
|
}}/>
|
||||||
class="secondary h-8 w-8 shrink-0 self-start rounded-full p-1"
|
|
||||||
aria-labelledby={config.editButtonAriaLabel === undefined ? answerId : undefined}
|
|
||||||
use:ariaLabel={config.editButtonAriaLabel}
|
|
||||||
>
|
|
||||||
<PencilAltIcon />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
|
|
|
@ -31,11 +31,10 @@ import OpeningHoursVisualization from "./OpeningHours/OpeningHoursVisualization"
|
||||||
import { SubtleButton } from "./Base/SubtleButton"
|
import { SubtleButton } from "./Base/SubtleButton"
|
||||||
import Svg from "../Svg"
|
import Svg from "../Svg"
|
||||||
import NoteCommentElement from "./Popup/Notes/NoteCommentElement"
|
import NoteCommentElement from "./Popup/Notes/NoteCommentElement"
|
||||||
import { SubstitutedTranslation } from "./SubstitutedTranslation"
|
|
||||||
import List from "./Base/List"
|
import List from "./Base/List"
|
||||||
import StatisticsPanel from "./BigComponents/StatisticsPanel"
|
import StatisticsPanel from "./BigComponents/StatisticsPanel"
|
||||||
import AutoApplyButton from "./Popup/AutoApplyButton"
|
import AutoApplyButton from "./Popup/AutoApplyButton"
|
||||||
import { LanguageElement } from "./Popup/LanguageElement"
|
import { LanguageElement } from "./Popup/LanguageElement/LanguageElement"
|
||||||
import FeatureReviews from "../Logic/Web/MangroveReviews"
|
import FeatureReviews from "../Logic/Web/MangroveReviews"
|
||||||
import Maproulette from "../Logic/Maproulette"
|
import Maproulette from "../Logic/Maproulette"
|
||||||
import SvelteUIElement from "./Base/SvelteUIElement"
|
import SvelteUIElement from "./Base/SvelteUIElement"
|
||||||
|
@ -88,6 +87,7 @@ import MaprouletteSetStatus from "./MapRoulette/MaprouletteSetStatus.svelte"
|
||||||
import DirectionIndicator from "./Base/DirectionIndicator.svelte"
|
import DirectionIndicator from "./Base/DirectionIndicator.svelte"
|
||||||
import Img from "./Base/Img"
|
import Img from "./Base/Img"
|
||||||
import Qr from "../Utils/Qr"
|
import Qr from "../Utils/Qr"
|
||||||
|
import SpecialTranslation from "./Popup/TagRendering/SpecialTranslation.svelte"
|
||||||
|
|
||||||
class NearbyImageVis implements SpecialVisualization {
|
class NearbyImageVis implements SpecialVisualization {
|
||||||
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
|
// 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()}?'",
|
docs: "Shows the title of the popup. Useful for some cases, e.g. 'What is phone number of {title()}?'",
|
||||||
example:
|
example:
|
||||||
"`What is the phone number of {title()}`, which might automatically become `What is the phone number of XYZ`.",
|
"`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<Record<string, string>>,
|
||||||
|
_: string[],
|
||||||
|
feature: Feature,
|
||||||
|
layer: LayerConfig
|
||||||
|
) =>
|
||||||
new VariableUiElement(
|
new VariableUiElement(
|
||||||
tagsSource.map((tags) => {
|
tagsSource.map((tags) => {
|
||||||
if (state.layout === undefined) {
|
if (state.layout === undefined) {
|
||||||
return "<feature title>"
|
return "<feature title>"
|
||||||
}
|
}
|
||||||
const layer = state.layout?.getMatchingLayer(tags)
|
|
||||||
const title = layer?.title?.GetRenderValue(tags)
|
const title = layer?.title?.GetRenderValue(tags)
|
||||||
if (title === undefined) {
|
if (title === undefined) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
return new SubstitutedTranslation(title, tagsSource, state).SetClass(
|
return new SvelteUIElement(SpecialTranslation, {
|
||||||
"px-1"
|
tags: tagsSource,
|
||||||
)
|
state,
|
||||||
|
feature,
|
||||||
|
layer,
|
||||||
|
}).SetClass("px-1")
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -1311,7 +1319,13 @@ export default class SpecialVisualizations {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
constr(state, featureTags, args) {
|
constr(
|
||||||
|
state: SpecialVisualizationState,
|
||||||
|
featureTags: UIEventSource<Record<string, string>>,
|
||||||
|
args: string[],
|
||||||
|
feature: Feature,
|
||||||
|
layer: LayerConfig
|
||||||
|
) {
|
||||||
const [key, tr] = args
|
const [key, tr] = args
|
||||||
const translation = new Translation({ "*": tr })
|
const translation = new Translation({ "*": tr })
|
||||||
return new VariableUiElement(
|
return new VariableUiElement(
|
||||||
|
@ -1319,11 +1333,13 @@ export default class SpecialVisualizations {
|
||||||
const properties: object[] = JSON.parse(tags[key])
|
const properties: object[] = JSON.parse(tags[key])
|
||||||
const elements = []
|
const elements = []
|
||||||
for (const property of properties) {
|
for (const property of properties) {
|
||||||
const subsTr = new SubstitutedTranslation(
|
const subsTr = new SvelteUIElement(SpecialTranslation, {
|
||||||
translation,
|
t: translation,
|
||||||
new UIEventSource<any>(property),
|
tags: properties,
|
||||||
state
|
state,
|
||||||
)
|
feature,
|
||||||
|
layer,
|
||||||
|
})
|
||||||
elements.push(subsTr)
|
elements.push(subsTr)
|
||||||
}
|
}
|
||||||
return new List(elements)
|
return new List(elements)
|
||||||
|
|
|
@ -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<Record<string, string>>,
|
|
||||||
state: SpecialVisualizationState,
|
|
||||||
mapping: Map<
|
|
||||||
string,
|
|
||||||
| BaseUIElement
|
|
||||||
| ((
|
|
||||||
state: SpecialVisualizationState,
|
|
||||||
tagSource: UIEventSource<Record<string, string>>,
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,16 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// Testing grounds
|
// Testing grounds
|
||||||
|
import LanguageElement from "./Popup/LanguageElement/LanguageElement.svelte"
|
||||||
|
import { UIEventSource } from "../Logic/UIEventSource"
|
||||||
|
|
||||||
import Icon from "./Map/Icon.svelte"
|
let tags = new UIEventSource({_country: "Be"})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Icon clss="h-16 w-16" icon="heart" color="#ff0000"/>
|
|
||||||
|
<LanguageElement
|
||||||
|
feature={undefined}
|
||||||
|
item_render={"{language()} is spoken here"}
|
||||||
|
key="language"
|
||||||
|
layer={undefined}
|
||||||
|
question="What languages are spoken here?"
|
||||||
|
render_all={"Following languages are spoken here: {list()}"} single_render={"Only {language()} is spoken here"} state={undefined} {tags} />
|
||||||
|
|
|
@ -9,8 +9,6 @@ export class Translation extends BaseUIElement {
|
||||||
|
|
||||||
public readonly translations: Record<string, string>
|
public readonly translations: Record<string, string>
|
||||||
public readonly context?: string
|
public readonly context?: string
|
||||||
|
|
||||||
private _current: Store<string>
|
|
||||||
private onDestroy: () => void
|
private onDestroy: () => void
|
||||||
|
|
||||||
constructor(translations: string | Record<string, string>, context?: string) {
|
constructor(translations: string | Record<string, string>, context?: string) {
|
||||||
|
@ -43,9 +41,11 @@ export class Translation extends BaseUIElement {
|
||||||
console.error(
|
console.error(
|
||||||
"Non-string object at",
|
"Non-string object at",
|
||||||
context,
|
context,
|
||||||
|
"of type",
|
||||||
|
typeof translations[translationsKey],
|
||||||
`for language`,
|
`for language`,
|
||||||
translationsKey,
|
translationsKey,
|
||||||
`in translation: `,
|
`. The offending object is: `,
|
||||||
translations[translationsKey],
|
translations[translationsKey],
|
||||||
"\n current translations are: ",
|
"\n current translations are: ",
|
||||||
translations
|
translations
|
||||||
|
@ -66,9 +66,7 @@ export class Translation extends BaseUIElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get txt(): string {
|
private _current: Store<string>
|
||||||
return this.textFor(Translation.forcedLanguage ?? Locale.language.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
get current(): Store<string> {
|
get current(): Store<string> {
|
||||||
if (!this._current) {
|
if (!this._current) {
|
||||||
|
@ -82,6 +80,11 @@ export class Translation extends BaseUIElement {
|
||||||
}
|
}
|
||||||
return this._current
|
return this._current
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get txt(): string {
|
||||||
|
return this.textFor(Translation.forcedLanguage ?? Locale.language.data)
|
||||||
|
}
|
||||||
|
|
||||||
static ExtractAllTranslationsFrom(
|
static ExtractAllTranslationsFrom(
|
||||||
object: any,
|
object: any,
|
||||||
context = ""
|
context = ""
|
||||||
|
@ -368,4 +371,32 @@ export class TypedTranslation<T extends Record<string, any>> extends Translation
|
||||||
|
|
||||||
return new TypedTranslation<Omit<T, X>>(newTranslations, this.context)
|
return new TypedTranslation<Omit<T, X>>(newTranslations, this.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PartialSubsTr<K extends string>(
|
||||||
|
key: string,
|
||||||
|
replaceWith: Translation
|
||||||
|
): TypedTranslation<Omit<T, K>> {
|
||||||
|
const newTranslations: Record<string, string> = {}
|
||||||
|
const toSearch = "{" + key + "}"
|
||||||
|
const missingLanguages = new Set<string>(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<Omit<T, K>>(newTranslations, this.context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue