Half complete i18n
This commit is contained in:
parent
7c1c9bc80a
commit
232664ee14
10 changed files with 100 additions and 24 deletions
|
@ -8,9 +8,9 @@ import {All} from "./Layouts/All";
|
||||||
import {Layout} from "./Layout";
|
import {Layout} from "./Layout";
|
||||||
|
|
||||||
export class AllKnownLayouts {
|
export class AllKnownLayouts {
|
||||||
public static allSets: any = AllKnownLayouts.AllLayouts();
|
public static allSets = AllKnownLayouts.AllLayouts();
|
||||||
|
|
||||||
private static AllLayouts() : any{
|
private static AllLayouts(): Map<string, Layout> {
|
||||||
const all = new All();
|
const all = new All();
|
||||||
const layouts : Layout[] = [
|
const layouts : Layout[] = [
|
||||||
new Groen(),
|
new Groen(),
|
||||||
|
@ -22,7 +22,7 @@ export class AllKnownLayouts {
|
||||||
new Statues(),
|
new Statues(),
|
||||||
*/
|
*/
|
||||||
];
|
];
|
||||||
const allSets = {};
|
const allSets: Map<string, Layout> = new Map();
|
||||||
for (const layout of layouts) {
|
for (const layout of layouts) {
|
||||||
allSets[layout.name] = layout;
|
allSets[layout.name] = layout;
|
||||||
all.layers = all.layers.concat(layout.layers);
|
all.layers = all.layers.concat(layout.layers);
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import {LayerDefinition} from "./LayerDefinition";
|
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).
|
* A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers).
|
||||||
*/
|
*/
|
||||||
export class Layout {
|
export class Layout {
|
||||||
public name: string;
|
public name: string;
|
||||||
public title: string;
|
public title: UIElement;
|
||||||
public layers: LayerDefinition[];
|
public layers: LayerDefinition[];
|
||||||
public welcomeMessage: string;
|
public welcomeMessage: UIElement;
|
||||||
public gettingStartedPlzLogin: string;
|
public gettingStartedPlzLogin: string;
|
||||||
public welcomeBackMessage: string;
|
public welcomeBackMessage: string;
|
||||||
|
|
||||||
|
@ -33,23 +35,23 @@ export class Layout {
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
name: string,
|
name: string,
|
||||||
title: string,
|
title: UIElement | string,
|
||||||
layers: LayerDefinition[],
|
layers: LayerDefinition[],
|
||||||
startzoom: number,
|
startzoom: number,
|
||||||
startLat: number,
|
startLat: number,
|
||||||
startLon: number,
|
startLon: number,
|
||||||
welcomeMessage: string,
|
welcomeMessage: UIElement | string,
|
||||||
gettingStartedPlzLogin: string = "Please login to get started",
|
gettingStartedPlzLogin: string = "Please login to get started",
|
||||||
welcomeBackMessage: string = "You are logged in. Welcome back!",
|
welcomeBackMessage: string = "You are logged in. Welcome back!",
|
||||||
welcomeTail: string = ""
|
welcomeTail: string = ""
|
||||||
) {
|
) {
|
||||||
this.title = title;
|
this.title = typeof(title) === 'string' ? new FixedUiElement(title) : title;
|
||||||
this.startLon = startLon;
|
this.startLon = startLon;
|
||||||
this.startLat = startLat;
|
this.startLat = startLat;
|
||||||
this.startzoom = startzoom;
|
this.startzoom = startzoom;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.layers = layers;
|
this.layers = layers;
|
||||||
this.welcomeMessage = welcomeMessage;
|
this.welcomeMessage = typeof(welcomeMessage) === 'string' ? new FixedUiElement(welcomeMessage) : welcomeMessage;
|
||||||
this.gettingStartedPlzLogin = gettingStartedPlzLogin;
|
this.gettingStartedPlzLogin = gettingStartedPlzLogin;
|
||||||
this.welcomeBackMessage = welcomeBackMessage;
|
this.welcomeBackMessage = welcomeBackMessage;
|
||||||
this.welcomeTail = welcomeTail;
|
this.welcomeTail = welcomeTail;
|
||||||
|
|
|
@ -2,27 +2,21 @@ import {Layout} from "../Layout";
|
||||||
import BikeParkings from "../Layers/BikeParkings";
|
import BikeParkings from "../Layers/BikeParkings";
|
||||||
import BikeServices from "../Layers/BikeStations";
|
import BikeServices from "../Layers/BikeStations";
|
||||||
import {GhostBike} from "../Layers/GhostBike";
|
import {GhostBike} from "../Layers/GhostBike";
|
||||||
|
import Translations from "../../UI/i18n/Translations";
|
||||||
|
|
||||||
|
|
||||||
export default class Cyclofix extends Layout {
|
export default class Cyclofix extends Layout {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(
|
super(
|
||||||
"pomp",
|
"pomp",
|
||||||
"Cyclofix bicycle infrastructure",
|
Translations.t.cylofix.title,
|
||||||
[new GhostBike(), new BikeServices(), new BikeParkings()],
|
[new GhostBike(), new BikeServices(), new BikeParkings()],
|
||||||
16,
|
16,
|
||||||
50.8465573,
|
50.8465573,
|
||||||
4.3516970,
|
4.3516970,
|
||||||
|
"<h3>" + Translations.t.cylofix.title.Render() + "</h3>\n" +
|
||||||
|
|
||||||
"<h3>Cyclofix bicycle infrastructure</h3>\n" +
|
|
||||||
"\n" +
|
"\n" +
|
||||||
"<p><b>EN></b> On this map we want to collect data about the whereabouts of bicycle pumps and public racks in Brussels." +
|
`<p>${Translations.t.cylofix.description.Render()}</p>`
|
||||||
"As a result, cyclists will be able to quickly find the nearest infrastructure for their needs.</p>" +
|
|
||||||
"<p><b>NL></b> 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.</p>" +
|
|
||||||
"<p><b>FR></b> 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.</p>"
|
|
||||||
,
|
,
|
||||||
"", "");
|
"", "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
||||||
* If 'question' is undefined, then the question is never asked at all
|
* If 'question' is undefined, then the question is never asked at all
|
||||||
* If the question is "" (empty string) then the question is
|
* If the question is "" (empty string) then the question is
|
||||||
*/
|
*/
|
||||||
question?: string,
|
question?: UIElement | string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What is the priority of the question.
|
* 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 }[],
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
18
UI/i18n/Locale.ts
Normal file
18
UI/i18n/Locale.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { UIEventSource } from "../UIEventSource";
|
||||||
|
|
||||||
|
|
||||||
|
const LANGUAGE_KEY = 'language'
|
||||||
|
|
||||||
|
export default class Locale {
|
||||||
|
public static language: UIEventSource<string> = new UIEventSource(Locale.getInitialLanguage())
|
||||||
|
|
||||||
|
public static init() {
|
||||||
|
Locale.language.addCallback(data => {
|
||||||
|
localStorage.setItem(LANGUAGE_KEY, data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private static getInitialLanguage() {
|
||||||
|
return localStorage.getItem(LANGUAGE_KEY)
|
||||||
|
}
|
||||||
|
}
|
16
UI/i18n/Translation.ts
Normal file
16
UI/i18n/Translation.ts
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
18
UI/i18n/Translations.ts
Normal file
18
UI/i18n/Translations.ts
Normal file
|
@ -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."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -238,6 +238,10 @@ form {
|
||||||
height: 1em;
|
height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#language-select {
|
||||||
|
pointer-events: all;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
#messagesbox-wrapper {
|
#messagesbox-wrapper {
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,11 @@
|
||||||
<br/>
|
<br/>
|
||||||
<div id="messagesbox-wrapper">
|
<div id="messagesbox-wrapper">
|
||||||
<div id="collapseButton"></div>
|
<div id="collapseButton"></div>
|
||||||
|
<select id="language-select">
|
||||||
|
<option>EN</option>
|
||||||
|
<option>NL</option>
|
||||||
|
<option>FR</option>
|
||||||
|
</select>
|
||||||
<div id="messagesbox"></div>
|
<div id="messagesbox"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
25
index.ts
25
index.ts
|
@ -22,6 +22,10 @@ import {SearchAndGo} from "./UI/SearchAndGo";
|
||||||
import {CollapseButton} from "./UI/Base/CollapseButton";
|
import {CollapseButton} from "./UI/Base/CollapseButton";
|
||||||
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
|
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
|
||||||
import {All} from "./Customizations/Layouts/All";
|
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;
|
dryRun = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const layoutToUse = AllKnownLayouts.allSets[defaultLayout];
|
const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout];
|
||||||
console.log("Using layout: ", layoutToUse.name);
|
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 -------------
|
// ----------------- Setup a few event sources -------------
|
||||||
|
@ -242,7 +249,7 @@ var welcomeMessage = () => {
|
||||||
login = layoutToUse.welcomeBackMessage;
|
login = layoutToUse.welcomeBackMessage;
|
||||||
}
|
}
|
||||||
return "<div id='welcomeMessage'>" +
|
return "<div id='welcomeMessage'>" +
|
||||||
layoutToUse.welcomeMessage + login + layoutToUse.welcomeTail +
|
layoutToUse.welcomeMessage.Render() + login + layoutToUse.welcomeTail +
|
||||||
"</div>";
|
"</div>";
|
||||||
}),
|
}),
|
||||||
function () {
|
function () {
|
||||||
|
@ -277,3 +284,15 @@ new GeoLocationHandler(bm).AttachTo("geolocate-button");
|
||||||
|
|
||||||
locationControl.ping();
|
locationControl.ping();
|
||||||
messageBox.update();
|
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')
|
||||||
|
|
Loading…
Reference in a new issue