Add progressive web app companion for cross-platform access
Vite + TypeScript PWA that mirrors the Android app's core features: - Pre-processed shelter data (build-time UTM33N→WGS84 conversion) - Leaflet map with shelter markers, user location, and offline tiles - Canvas compass arrow (ported from DirectionArrowView.kt) - IndexedDB shelter cache with 7-day staleness check - Service worker with CacheFirst tiles and precached app shell - i18n for en, nb, nn (ported from Android strings.xml) - iOS/Android compass handling with low-pass filter - Respects user map interaction (no auto-snap on pan/zoom) - Build revision cache-breaker for reliable SW updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
46365b713b
commit
e8428de775
12051 changed files with 1799735 additions and 0 deletions
49
pwa/src/i18n/i18n.ts
Normal file
49
pwa/src/i18n/i18n.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Minimal i18n system: detects locale from navigator.languages,
|
||||
* provides t(key, ...args) for string lookup with %d/%s substitution.
|
||||
*/
|
||||
|
||||
import { en } from './en';
|
||||
import { nb } from './nb';
|
||||
import { nn } from './nn';
|
||||
|
||||
const locales: Record<string, Record<string, string>> = { en, nb, nn };
|
||||
|
||||
let currentLocale = 'en';
|
||||
|
||||
/** Detect and set locale from browser preferences. */
|
||||
export function initLocale(): void {
|
||||
const langs = navigator.languages ?? [navigator.language];
|
||||
for (const lang of langs) {
|
||||
const code = lang.toLowerCase().split('-')[0];
|
||||
if (code in locales) {
|
||||
currentLocale = code;
|
||||
return;
|
||||
}
|
||||
// nb and nn both start with "n" — also match "no" as Bokmål
|
||||
if (code === 'no') {
|
||||
currentLocale = 'nb';
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Get current locale code. */
|
||||
export function getLocale(): string {
|
||||
return currentLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a string key, substituting %d and %s with provided arguments.
|
||||
* Falls back to English, then to the raw key.
|
||||
*/
|
||||
export function t(key: string, ...args: (string | number)[]): string {
|
||||
let str = locales[currentLocale]?.[key] ?? locales.en[key] ?? key;
|
||||
|
||||
// Replace %d and %s placeholders sequentially
|
||||
for (const arg of args) {
|
||||
str = str.replace(/%[ds]/, String(arg));
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue