From 232664ee14fac71cc6ce2cc06fe5ed0f06ec5273 Mon Sep 17 00:00:00 2001 From: Pieter Fiers Date: Mon, 20 Jul 2020 12:39:43 +0200 Subject: [PATCH] Half complete i18n --- Customizations/AllKnownLayouts.ts | 6 +++--- Customizations/Layout.ts | 14 ++++++++------ Customizations/Layouts/Cyclofix.ts | 14 ++++---------- Customizations/TagRendering.ts | 4 ++-- UI/i18n/Locale.ts | 18 ++++++++++++++++++ UI/i18n/Translation.ts | 16 ++++++++++++++++ UI/i18n/Translations.ts | 18 ++++++++++++++++++ index.css | 4 ++++ index.html | 5 +++++ index.ts | 25 ++++++++++++++++++++++--- 10 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 UI/i18n/Locale.ts create mode 100644 UI/i18n/Translation.ts create mode 100644 UI/i18n/Translations.ts diff --git a/Customizations/AllKnownLayouts.ts b/Customizations/AllKnownLayouts.ts index 9a8728e..cc4f2fb 100644 --- a/Customizations/AllKnownLayouts.ts +++ b/Customizations/AllKnownLayouts.ts @@ -8,9 +8,9 @@ import {All} from "./Layouts/All"; import {Layout} from "./Layout"; export class AllKnownLayouts { - public static allSets: any = AllKnownLayouts.AllLayouts(); + public static allSets = AllKnownLayouts.AllLayouts(); - private static AllLayouts() : any{ + private static AllLayouts(): Map { const all = new All(); const layouts : Layout[] = [ new Groen(), @@ -22,7 +22,7 @@ export class AllKnownLayouts { new Statues(), */ ]; - const allSets = {}; + const allSets: Map = new Map(); for (const layout of layouts) { allSets[layout.name] = layout; all.layers = all.layers.concat(layout.layers); diff --git a/Customizations/Layout.ts b/Customizations/Layout.ts index 7c72927..a1d888e 100644 --- a/Customizations/Layout.ts +++ b/Customizations/Layout.ts @@ -1,13 +1,15 @@ import {LayerDefinition} from "./LayerDefinition"; +import { UIElement } from "../UI/UIElement"; +import { FixedUiElement } from "../UI/Base/FixedUiElement"; /** * A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers). */ export class Layout { public name: string; - public title: string; + public title: UIElement; public layers: LayerDefinition[]; - public welcomeMessage: string; + public welcomeMessage: UIElement; public gettingStartedPlzLogin: string; public welcomeBackMessage: string; @@ -33,23 +35,23 @@ export class Layout { */ constructor( name: string, - title: string, + title: UIElement | string, layers: LayerDefinition[], startzoom: number, startLat: number, startLon: number, - welcomeMessage: string, + welcomeMessage: UIElement | string, gettingStartedPlzLogin: string = "Please login to get started", welcomeBackMessage: string = "You are logged in. Welcome back!", welcomeTail: string = "" ) { - this.title = title; + this.title = typeof(title) === 'string' ? new FixedUiElement(title) : title; this.startLon = startLon; this.startLat = startLat; this.startzoom = startzoom; this.name = name; this.layers = layers; - this.welcomeMessage = welcomeMessage; + this.welcomeMessage = typeof(welcomeMessage) === 'string' ? new FixedUiElement(welcomeMessage) : welcomeMessage; this.gettingStartedPlzLogin = gettingStartedPlzLogin; this.welcomeBackMessage = welcomeBackMessage; this.welcomeTail = welcomeTail; diff --git a/Customizations/Layouts/Cyclofix.ts b/Customizations/Layouts/Cyclofix.ts index 9ed6a3b..328acda 100644 --- a/Customizations/Layouts/Cyclofix.ts +++ b/Customizations/Layouts/Cyclofix.ts @@ -2,27 +2,21 @@ import {Layout} from "../Layout"; import BikeParkings from "../Layers/BikeParkings"; import BikeServices from "../Layers/BikeStations"; import {GhostBike} from "../Layers/GhostBike"; +import Translations from "../../UI/i18n/Translations"; export default class Cyclofix extends Layout { constructor() { super( "pomp", - "Cyclofix bicycle infrastructure", + Translations.t.cylofix.title, [new GhostBike(), new BikeServices(), new BikeParkings()], 16, 50.8465573, 4.3516970, - - - "

Cyclofix bicycle infrastructure

\n" + + "

" + Translations.t.cylofix.title.Render() + "

\n" + "\n" + - "

EN> On this map we want to collect data about the whereabouts of bicycle pumps and public racks in Brussels." + - "As a result, cyclists will be able to quickly find the nearest infrastructure for their needs.

" + - "

NL> Op deze kaart willen we gegevens verzamelen over de locatie van fietspompen en openbare stelplaatsen in Brussel." + - "Hierdoor kunnen fietsers snel de dichtstbijzijnde infrastructuur vinden die voldoet aan hun behoeften.

" + - "

FR> Sur cette carte, nous voulons collecter des données sur la localisation des pompes à vélo et des supports publics à Bruxelles." + - "Les cyclistes pourront ainsi trouver rapidement l'infrastructure la plus proche de leurs besoins.

" + `

${Translations.t.cylofix.description.Render()}

` , "", ""); } diff --git a/Customizations/TagRendering.ts b/Customizations/TagRendering.ts index c5f8d63..60b0713 100644 --- a/Customizations/TagRendering.ts +++ b/Customizations/TagRendering.ts @@ -35,7 +35,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor { * If 'question' is undefined, then the question is never asked at all * If the question is "" (empty string) then the question is */ - question?: string, + question?: UIElement | string, /** * What is the priority of the question. @@ -56,7 +56,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor { * * */ - mappings?: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[], + mappings?: { k: TagsFilter, txt: UIElement | string, priority?: number, substitute?: boolean }[], /** diff --git a/UI/i18n/Locale.ts b/UI/i18n/Locale.ts new file mode 100644 index 0000000..52c45bb --- /dev/null +++ b/UI/i18n/Locale.ts @@ -0,0 +1,18 @@ +import { UIEventSource } from "../UIEventSource"; + + +const LANGUAGE_KEY = 'language' + +export default class Locale { + public static language: UIEventSource = new UIEventSource(Locale.getInitialLanguage()) + + public static init() { + Locale.language.addCallback(data => { + localStorage.setItem(LANGUAGE_KEY, data) + }) + } + + private static getInitialLanguage() { + return localStorage.getItem(LANGUAGE_KEY) + } +} diff --git a/UI/i18n/Translation.ts b/UI/i18n/Translation.ts new file mode 100644 index 0000000..4b53b17 --- /dev/null +++ b/UI/i18n/Translation.ts @@ -0,0 +1,16 @@ +import { UIElement } from "../UIElement" +import Locale from "./Locale" + + +export default class Translation extends UIElement{ + protected InnerRender(): string { + return this.translations[Locale.language.data] + } + + public readonly translations: object + + constructor(translations: object) { + super(Locale.language) + this.translations = translations + } +} diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts new file mode 100644 index 0000000..edf0561 --- /dev/null +++ b/UI/i18n/Translations.ts @@ -0,0 +1,18 @@ +import Translation from "./Translation"; + + +export default class Translations { + static t = { + cylofix: { + title: new Translation({en: 'Cyclofix bicycle infrastructure', nl: 'Cyclofix fietsinfrastructuur', fr: 'TODO: FRENCH TRANSLATION'}), + description: new Translation({ + en: "On this map we want to collect data about the whereabouts of bicycle pumps and public racks in Brussels." + + "As a result, cyclists will be able to quickly find the nearest infrastructure for their needs.", + nl: "Op deze kaart willen we gegevens verzamelen over de locatie van fietspompen en openbare stelplaatsen in Brussel." + + "Hierdoor kunnen fietsers snel de dichtstbijzijnde infrastructuur vinden die voldoet aan hun behoeften.", + fr: "Sur cette carte, nous voulons collecter des données sur la localisation des pompes à vélo et des supports publics à Bruxelles." + + "Les cyclistes pourront ainsi trouver rapidement l'infrastructure la plus proche de leurs besoins." + }) + } + } +} diff --git a/index.css b/index.css index c86b574..672e558 100644 --- a/index.css +++ b/index.css @@ -238,6 +238,10 @@ form { height: 1em; } +#language-select { + pointer-events: all; + cursor: pointer; +} #messagesbox-wrapper { } diff --git a/index.html b/index.html index 16c5387..bcdeca3 100644 --- a/index.html +++ b/index.html @@ -34,6 +34,11 @@
+
diff --git a/index.ts b/index.ts index 6696d39..0e41b1f 100644 --- a/index.ts +++ b/index.ts @@ -22,6 +22,10 @@ import {SearchAndGo} from "./UI/SearchAndGo"; import {CollapseButton} from "./UI/Base/CollapseButton"; import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; import {All} from "./Customizations/Layouts/All"; +import Translations from "./UI/i18n/Translations"; +import Translation from "./UI/i18n/Translation"; +import Locale from "./UI/i18n/Locale"; +import { Layout } from "./Customizations/Layout"; @@ -87,10 +91,13 @@ if (paramDict.test) { dryRun = true; } -const layoutToUse = AllKnownLayouts.allSets[defaultLayout]; +const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout]; console.log("Using layout: ", layoutToUse.name); -document.title = layoutToUse.title; +document.title = layoutToUse.title.Render(); +Locale.language.addCallback(e => { + document.title = layoutToUse.title.Render(); +}) // ----------------- Setup a few event sources ------------- @@ -242,7 +249,7 @@ var welcomeMessage = () => { login = layoutToUse.welcomeBackMessage; } return "
" + - layoutToUse.welcomeMessage + login + layoutToUse.welcomeTail + + layoutToUse.welcomeMessage.Render() + login + layoutToUse.welcomeTail + "
"; }), function () { @@ -277,3 +284,15 @@ new GeoLocationHandler(bm).AttachTo("geolocate-button"); locationControl.ping(); messageBox.update(); + + +// --- Locale --- + +Locale.init() + +window.setLanguage = function(language:string) { + Locale.language.setData(language) +} + +// const eLanguageSelect = document.getElementById('language-select') as HTMLOptionElement +// eLanguageSelect.addEventListener('selectionchange')