Skip to content

Commit

Permalink
multi language support for web ui
Browse files Browse the repository at this point in the history
  • Loading branch information
felixguendling committed Nov 19, 2024
1 parent d773eac commit 55343e1
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 25 deletions.
8 changes: 3 additions & 5 deletions ui/src/lib/AddressTypeahead.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
import { Combobox } from 'bits-ui';
import { cn } from './utils';
import { geocode, type Match } from './openapi';
import { browser } from '$app/environment';
import Bus from 'lucide-svelte/icons/bus-front';
import House from 'lucide-svelte/icons/map-pin-house';
import Place from 'lucide-svelte/icons/map-pin';
import { posToLocation, type Location } from './Location';
import { GEOCODER_PRECISION } from './Precision';
import { language } from './i18n/translation';
const COORD_LVL_REGEX = /([+-]?\d+(\.\d+)?)\s*,\s*([+-]?\d+(\.\d+)?)\s*,\s*([+-]?\d+(\.\d+)?)/;
const COORD_REGEX = /([+-]?\d+(\.\d+)?)\s*,\s*([+-]?\d+(\.\d+)?)/;
const COORD_LVL_REGEX = /^([+-]?\d+(\.\d+)?)\s*,\s*([+-]?\d+(\.\d+)?)\s*,\s*([+-]?\d+(\.\d+)?)$/;
const COORD_REGEX = /^([+-]?\d+(\.\d+)?)\s*,\s*([+-]?\d+(\.\d+)?)$/;
let {
items = $bindable([]),
Expand All @@ -31,8 +31,6 @@
let inputValue = $state('');
let touchedInput = $state(false);
const language = browser ? navigator.languages.find((l) => l.length == 2) : '';
const getDisplayArea = (match: Match | undefined) => {
if (match) {
const matchedArea = match.areas.find((a) => a.matched);
Expand Down
30 changes: 30 additions & 0 deletions ui/src/lib/i18n/de.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { Translations } from './translation';

const translations: Translations = {
from: 'Von',
to: 'Nach',
arrival: 'Ankunft',
departure: 'Abfahrt',
duration: 'Dauer',
arrivals: 'Ankünfte',
departures: 'Abfahrten',
later: 'später',
earlier: 'früher',
track: 'Gleis',
arrivalOnTrack: 'Ankunft auf Gleis',
switchToArrivals: 'Wechsel zu Ankünften',
switchToDepartures: 'Wechsel zu Abfahrten',
tripIntermediateStops: (n: number) => {
switch (n) {
case 0:
return 'Fahrt ohne Zwischenhalt';
case 1:
return 'Fahrt eine Station';
default:
return `Fahrt ${n} Stationen`;
}
},
sharingProvider: 'Anbieter'
};

export default translations;
30 changes: 30 additions & 0 deletions ui/src/lib/i18n/en.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { Translations } from './translation';

const translations: Translations = {
from: 'From',
to: 'To',
arrival: 'Arrival',
departure: 'Departure',
duration: 'Duration',
arrivals: 'Arrivals',
later: 'later',
earlier: 'earlier',
departures: 'Departures',
switchToArrivals: 'Wechsel zu Ankünften',
switchToDepartures: 'Wechsel zu Abfahrten',
track: 'Track',
arrivalOnTrack: 'Arrival on track',
tripIntermediateStops: (n: number) => {
switch (n) {
case 0:
return 'No intermediate stops';
case 1:
return '1 intermediate stop';
default:
return `${n} intermediate stops`;
}
},
sharingProvider: 'Provider'
};

export default translations;
31 changes: 31 additions & 0 deletions ui/src/lib/i18n/translation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { browser } from '$app/environment';
import en from './en';
import de from './de';

export type Translations = {
from: string;
to: string;
arrival: string;
departure: string;
duration: string;
later: string;
earlier: string;
arrivals: string;
departures: string;
switchToArrivals: string;
switchToDepartures: string;
arrivalOnTrack: string;
track: string;
tripIntermediateStops: (n: number) => string;
sharingProvider: string;
};

const translations: Map<string, Translations> = new Map(
Object.entries({
en,
de
})
);

export const language = (browser ? navigator.languages.find((l) => l.length == 2) : 'en') ?? 'en';
export const t = translations.get(language) ?? en;
5 changes: 3 additions & 2 deletions ui/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import StopTimes from './StopTimes.svelte';
import { onMount } from 'svelte';
import RailViz from './RailViz.svelte';
import { t } from '$lib/i18n/translation';
const urlParams = browser ? new URLSearchParams(window.location.search) : undefined;
const hasDebug = urlParams && urlParams.has('debug');
Expand Down Expand Up @@ -279,9 +280,9 @@
<div class="w-full flex justify-between items-center shadow-md pl-1 mb-1">
<h2 class="ml-2 text-base font-semibold">
{#if stopArriveBy}
Ankünfte
{t.arrivals}
{:else}
Abfahrten
{t.departures}
{/if}
in
{selectedStop.name}
Expand Down
13 changes: 8 additions & 5 deletions ui/src/routes/ConnectionDetail.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { Button } from '$lib/components/ui/button';
import Route from '$lib/Route.svelte';
import { getModeName } from '$lib/getModeName';
import { t } from '$lib/i18n/translation';
const {
itinerary,
Expand Down Expand Up @@ -60,7 +61,7 @@
</span>
{#if l.rental && l.rental.systemName}
<span class="ml-6">
Anbieter: <a href={l.rental.url} target="_blank">{l.rental.systemName}</a>
{t.sharingProvider}: <a href={l.rental.url} target="_blank">{l.rental.systemName}</a>
</span>
{/if}
</div>
Expand All @@ -80,7 +81,7 @@
<div class="border-t w-full h-0"></div>
<div class="text-sm text-muted-foreground text-nowrap px-2">
{#if pred.from.track}
Ankunft auf Gleis {pred.from.track}{pred.duration ? ',' : ''}
{t.arrivalOnTrack} {pred.from.track}{pred.duration ? ',' : ''}
{/if}
{#if pred.duration}
{formatDurationSec(pred.duration)} Fußweg
Expand All @@ -93,7 +94,8 @@
<div class="border-t w-full h-0"></div>
{#if l.from.track}
<div class="text-nowrap border rounded-xl px-2">
Gleis {l.from.track}
{t.track}
{l.from.track}
</div>
{/if}
</div>
Expand All @@ -114,7 +116,7 @@
</div>
{#if l.intermediateStops?.length === 0}
<div class="py-12 pl-8 flex items-center text-muted-foreground">
Fahrt ohne Zwischenhalt
{t.tripIntermediateStops(0)}
</div>
{:else}
<details class="[&_svg]:open:-rotate-180">
Expand All @@ -133,7 +135,8 @@
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
<span class="ml-2 cursor-pointer">
Fahrt {l.intermediateStops?.length} Station ({formatDurationSec(l.duration)})
{t.tripIntermediateStops(l.intermediateStops?.length ?? 0)}
({formatDurationSec(l.duration)})
</span>
</summary>
<div class="mb-6 grid gap-y-6 grid-cols-7 items-center">
Expand Down
11 changes: 6 additions & 5 deletions ui/src/routes/ItineraryList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { plan, type Itinerary, type Leg, type PlanData, type PlanResponse } from '$lib/openapi';
import Time from '$lib/Time.svelte';
import LoaderCircle from 'lucide-svelte/icons/loader-circle';
import { t } from '$lib/i18n/translation';
let {
routingResponses,
Expand Down Expand Up @@ -79,7 +80,7 @@
}}
class="px-2 py-1 bg-blue-600 hover:!bg-blue-700 text-white font-bold text-sm border rounded-lg"
>
früher
{t.earlier}
</button>
<div class="border-t w-full h-0"></div>
</div>
Expand All @@ -93,7 +94,7 @@
<Card class="p-4">
<div class="text-base h-8 flex justify-between items-center space-x-4 w-full">
<div>
<div class="text-xs font-bold uppercase text-slate-400">Departure</div>
<div class="text-xs font-bold uppercase text-slate-400">{t.departure}</div>
<Time
isRealtime={it.legs[0].realTime}
timestamp={it.startTime}
Expand All @@ -103,7 +104,7 @@
</div>
<Separator orientation="vertical" />
<div>
<div class="text-xs font-bold uppercase text-slate-400">Arrival</div>
<div class="text-xs font-bold uppercase text-slate-400">{t.arrival}</div>
<Time
isRealtime={it.legs[it.legs.length - 1].realTime}
timestamp={it.endTime}
Expand All @@ -118,7 +119,7 @@
</div>
<Separator orientation="vertical" />
<div>
<div class="text-xs font-bold uppercase text-slate-400">Duration</div>
<div class="text-xs font-bold uppercase text-slate-400">{t.duration}</div>
<div class="flex justify-center w-full">
{formatDurationSec(it.duration)}
</div>
Expand Down Expand Up @@ -146,7 +147,7 @@
}}
class="px-2 py-1 bg-blue-600 hover:!bg-blue-700 text-white text-sm font-bold border rounded-lg"
>
später
{t.later}
</button>
<div class="border-t w-full h-0"></div>
</div>
Expand Down
9 changes: 5 additions & 4 deletions ui/src/routes/SearchMask.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import DateInput from '$lib/DateInput.svelte';
import { type Location } from '$lib/Location';
import { Toggle } from '$lib/components/ui/toggle';
import { t } from '$lib/i18n/translation';
let {
from = $bindable(),
Expand Down Expand Up @@ -36,15 +37,15 @@
<AddressTypeahead
name="from"
class="w-full"
placeholder="From"
placeholder={t.from}
bind:selected={from}
bind:items={fromItems}
{theme}
/>
<AddressTypeahead
name="to"
class="w-full"
placeholder="To"
placeholder={t.to}
bind:selected={to}
bind:items={toItems}
{theme}
Expand Down Expand Up @@ -73,14 +74,14 @@
class="flex items-center rounded-md border-2 border-muted bg-popover p-1 px-2 hover:bg-accent hover:text-accent-foreground [&:has([data-state=checked])]:border-blue-600 hover:cursor-pointer"
>
<RadioGroup.Item value="departure" id="departure" class="sr-only" aria-label="Abfahrt" />
<span>Abfahrt</span>
<span>{t.departure}</span>
</Label>
<Label
for="arrival"
class="flex items-center rounded-md border-2 border-muted bg-popover p-1 px-2 hover:bg-accent hover:text-accent-foreground [&:has([data-state=checked])]:border-blue-600 hover:cursor-pointer"
>
<RadioGroup.Item value="arrival" id="arrival" class="sr-only" aria-label="Ankunft" />
<span>Ankunft</span>
<span>{t.arrival}</span>
</Label>
</RadioGroup.Root>
<Toggle aria-label="toggle bold" bind:pressed={wheelchair}>
Expand Down
9 changes: 5 additions & 4 deletions ui/src/routes/StopTimes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import Time from '$lib/Time.svelte';
import Route from '$lib/Route.svelte';
import { Button } from '$lib/components/ui/button';
import { t } from '$lib/i18n/translation';
let {
stopId,
Expand Down Expand Up @@ -35,9 +36,9 @@
}}
>
{#if arriveBy}
Wechsel zu Abfahrten
{t.switchToDepartures}
{:else}
Wechsel zu Ankünften
{t.switchToArrivals}
{/if}
</Button>
</div>
Expand All @@ -62,7 +63,7 @@
}}
class="px-2 py-1 bg-blue-600 hover:!bg-blue-700 text-white font-bold text-sm border rounded-lg"
>
früher
{t.earlier}
</button>
<div class="border-t w-full h-0"></div>
</div>
Expand Down Expand Up @@ -111,7 +112,7 @@
}}
class="px-2 py-1 bg-blue-600 hover:!bg-blue-700 text-white text-sm font-bold border rounded-lg"
>
später
{t.later}
</button>
<div class="border-t w-full h-0"></div>
</div>
Expand Down

0 comments on commit 55343e1

Please sign in to comment.