remove svelte-i18n dependency, replace with minimalistic implementation

This commit is contained in:
vcoppe
2025-06-08 13:49:39 +02:00
parent a9ea0e223d
commit 228ad1044e
59 changed files with 121 additions and 746 deletions

View File

@@ -2,7 +2,7 @@
import docsearch from '@docsearch/js';
import '@docsearch/css';
import { onMount } from 'svelte';
import { _, locale, waitLocale } from 'svelte-i18n';
import { _, locale, isLoadingLocale } from '$lib/i18n';
let mounted = false;
@@ -13,7 +13,7 @@
indexName: 'gpx',
container: '#docsearch',
searchParameters: {
facetFilters: ['lang:' + ($locale ?? 'en')],
facetFilters: ['lang:' + $locale],
},
placeholder: $_('docs.search.search'),
disableUserPersonalization: true,
@@ -48,8 +48,8 @@
mounted = true;
});
$: if (mounted && $locale) {
waitLocale().then(initDocsearch);
$: if (mounted && $locale && !$isLoadingLocale) {
initDocsearch();
}
</script>

View File

@@ -20,7 +20,7 @@
Construction,
} from 'lucide-svelte';
import { getSlopeColor, getSurfaceColor, getHighwayColor } from '$lib/assets/colors';
import { _ } from 'svelte-i18n';
import { _, df } from '$lib/i18n';
import {
getCadenceWithUnits,
getConvertedDistance,
@@ -39,7 +39,6 @@
import type { GPXStatistics } from 'gpx';
import { settings } from '$lib/db';
import { mode } from 'mode-watcher';
import { df } from '$lib/utils';
export let gpxStatistics: Writable<GPXStatistics>;
export let slicedGPXStatistics: Writable<[GPXStatistics, number, number] | undefined>;
@@ -177,7 +176,7 @@
}
if (point.time) {
labels.push(` ${$_('quantities.time')}: ${df.format(point.time)}`);
labels.push(` ${$_('quantities.time')}: ${$df.format(point.time)}`);
}
return labels;

View File

@@ -22,7 +22,7 @@
Thermometer,
SquareActivity,
} from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { selection } from './file-list/Selection';
import { get } from 'svelte/store';
import { GPXStatistics } from 'gpx';

View File

@@ -3,7 +3,7 @@
import LanguageSelect from '$lib/components/LanguageSelect.svelte';
import Logo from '$lib/components/Logo.svelte';
import { AtSign, BookOpenText, Heart, Home, Map } from 'lucide-svelte';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { getURLForLanguage } from '$lib/utils';
</script>

View File

@@ -5,7 +5,7 @@
import { MoveDownRight, MoveUpRight, Ruler, Timer, Zap } from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import type { GPXStatistics } from 'gpx';
import type { Writable } from 'svelte/store';
import { settings } from '$lib/db';

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { CircleHelp } from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
export let link: string | undefined = undefined;
</script>

View File

@@ -4,7 +4,7 @@
import { languages } from '$lib/languages';
import { getURLForLanguage } from '$lib/utils';
import { Languages } from 'lucide-svelte';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
let selected = {
value: '',

View File

@@ -10,7 +10,7 @@
import { Button } from '$lib/components/ui/button';
import { map } from '$lib/stores';
import { settings } from '$lib/db';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { PUBLIC_MAPBOX_TOKEN } from '$env/static/public';
import { page } from '$app/stores';

View File

@@ -74,7 +74,7 @@
import { allowedPastes, ListFileItem, ListTrackItem } from '$lib/components/file-list/FileList';
import Export from '$lib/components/Export.svelte';
import { mode, setMode, systemPrefersMode } from 'mode-watcher';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { languages } from '$lib/languages';
import { getURLForLanguage } from '$lib/utils';
@@ -450,7 +450,7 @@
{$_('menu.language')}
</Menubar.SubTrigger>
<Menubar.SubContent>
<Menubar.RadioGroup bind:value={$locale}>
<Menubar.RadioGroup value={$locale}>
{#each Object.entries(languages) as [lang, label]}
<a href={getURLForLanguage(lang, '/app')}>
<Menubar.RadioItem value={lang}>{label}</Menubar.RadioItem>

View File

@@ -2,7 +2,7 @@
import { Button } from '$lib/components/ui/button';
import { Moon, Sun } from 'lucide-svelte';
import { mode, setMode, systemPrefersMode } from 'mode-watcher';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
export let size = '20';

View File

@@ -4,7 +4,7 @@
import AlgoliaDocSearch from '$lib/components/AlgoliaDocSearch.svelte';
import ModeSwitch from '$lib/components/ModeSwitch.svelte';
import { BookOpenText, Home, Map } from 'lucide-svelte';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { getURLForLanguage } from '$lib/utils';
</script>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { isMac, isSafari } from '$lib/utils';
import { onMount } from 'svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
export let key: string | undefined = undefined;
export let shift: boolean = false;

View File

@@ -11,7 +11,7 @@
secondsToHHMMSS,
} from '$lib/units';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
export let value: number;
export let type: 'distance' | 'elevation' | 'speed' | 'temperature' | 'time';

View File

@@ -1,6 +1,4 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
export let module;
</script>

View File

@@ -15,7 +15,7 @@
Milestone,
Video,
} from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import {
allowedEmbeddingBasemaps,
getCleanedEmbeddingOptions,

View File

@@ -2,7 +2,7 @@
import { Button } from '$lib/components/ui/button';
import Logo from '$lib/components/Logo.svelte';
import { getURLForLanguage } from '$lib/utils';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
export let files: string[];
export let ids: string[];

View File

@@ -8,7 +8,7 @@
import { copied, pasteSelection, selectAll, selection } from './Selection';
import { ClipboardPaste, FileStack, Plus } from 'lucide-svelte';
import Shortcut from '$lib/components/Shortcut.svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { createFile } from '$lib/stores';
export let orientation: 'vertical' | 'horizontal';

View File

@@ -21,7 +21,7 @@
type ListItem,
type ListTrackItem,
} from './FileList';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { selection } from './Selection';
export let node:

View File

@@ -23,7 +23,7 @@
} from './FileList';
import { selection } from './Selection';
import { isMac } from '$lib/utils';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
export let node:
| Map<string, Readable<GPXFileWithStatistics | undefined>>

View File

@@ -50,7 +50,7 @@
map,
} from '$lib/stores';
import { GPXTreeElement, Track, type AnyGPXTreeElement, Waypoint, GPXFile } from 'gpx';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import MetadataDialog from './MetadataDialog.svelte';
import StyleDialog from './StyleDialog.svelte';
import { waypointPopup } from '$lib/components/gpx-layer/GPXLayerPopup';

View File

@@ -8,7 +8,7 @@
import { Save } from 'lucide-svelte';
import { ListFileItem, ListTrackItem, type ListItem } from './FileList';
import { GPXTreeElement, Track, type AnyGPXTreeElement, Waypoint, GPXFile } from 'gpx';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { editMetadata } from '$lib/stores';
export let node: GPXTreeElement<AnyGPXTreeElement> | Waypoint[] | Waypoint;

View File

@@ -9,7 +9,7 @@
import { ListFileItem, ListTrackItem, type ListItem } from './FileList';
import { selection } from './Selection';
import { editStyle, gpxLayers } from '$lib/stores';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
export let item: ListItem;
export let open = false;

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { Button } from '$lib/components/ui/button';
import { ClipboardCopy } from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import type { Coordinates } from 'gpx';
export let coordinates: Coordinates;

View File

@@ -5,8 +5,7 @@
import * as Card from '$lib/components/ui/card';
import WithUnits from '$lib/components/WithUnits.svelte';
import { Compass, Mountain, Timer } from 'lucide-svelte';
import { df } from '$lib/utils';
import { _ } from 'svelte-i18n';
import { _, df } from '$lib/i18n';
export let trackpoint: PopupItem<TrackPoint>;
</script>
@@ -31,7 +30,7 @@
{#if trackpoint.item.time}
<div class="flex flex-row items-center gap-1">
<Timer size="14" />
{df.format(trackpoint.item.time)}
{$df.format(trackpoint.item.time)}
</div>
{/if}
<CopyCoordinates

View File

@@ -8,7 +8,7 @@
import { Dot, ExternalLink, Trash2 } from 'lucide-svelte';
import { Tool, currentTool } from '$lib/stores';
import { getSymbolKey, symbols } from '$lib/assets/symbols';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import sanitizeHtml from 'sanitize-html';
import type { Waypoint } from 'gpx';
import type { PopupItem } from '$lib/components/MapPopup';

View File

@@ -17,7 +17,7 @@
Map,
Layers2,
} from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { settings } from '$lib/db';
import { defaultBasemap, type CustomLayer } from '$lib/assets/layers';
import { map } from '$lib/stores';

View File

@@ -19,7 +19,7 @@
import { getLayers, isSelected, toggle } from '$lib/components/layer-control/utils';
import { settings } from '$lib/db';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { writable } from 'svelte/store';
import { map } from '$lib/stores';
import CustomLayers from './CustomLayers.svelte';

View File

@@ -6,7 +6,7 @@
import { type LayerTreeType } from '$lib/assets/layers';
import { anySelectedLayer } from './utils';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { settings } from '$lib/db';
import { beforeUpdate } from 'svelte';

View File

@@ -3,7 +3,7 @@
import { Button } from '$lib/components/ui/button';
import { selection } from '$lib/components/file-list/Selection';
import { PencilLine, MapPin } from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { dbUtils } from '$lib/db';
import type { PopupItem } from '$lib/components/MapPopup';
import { ScrollArea } from '$lib/components/ui/scroll-area/index.js';

View File

@@ -7,7 +7,7 @@
import { GoogleRedirect } from './Google';
import { map, streetViewEnabled } from '$lib/stores';
import { settings } from '$lib/db';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { writable } from 'svelte/store';
const { streetViewSource } = settings;

View File

@@ -13,7 +13,7 @@
MountainSnow,
} from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import ToolbarItemMenu from './ToolbarItemMenu.svelte';
</script>

View File

@@ -11,7 +11,7 @@
import * as RadioGroup from '$lib/components/ui/radio-group';
import { Button } from '$lib/components/ui/button';
import Help from '$lib/components/Help.svelte';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { onDestroy, onMount } from 'svelte';
import { getURLForLanguage, resetCursor, setCrosshairCursor } from '$lib/utils';
import { Trash2 } from 'lucide-svelte';

View File

@@ -5,7 +5,7 @@
import { MountainSnow } from 'lucide-svelte';
import { dbUtils } from '$lib/db';
import { map } from '$lib/stores';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { getURLForLanguage } from '$lib/utils';
$: validSelection = $selection.size > 0;

View File

@@ -11,7 +11,7 @@
} from '$lib/components/file-list/FileList';
import Help from '$lib/components/Help.svelte';
import { dbUtils, getFile } from '$lib/db';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { getURLForLanguage } from '$lib/utils';
$: validSelection =

View File

@@ -13,7 +13,7 @@
import { Label } from '$lib/components/ui/label/index.js';
import { Checkbox } from '$lib/components/ui/checkbox';
import * as RadioGroup from '$lib/components/ui/radio-group';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { dbUtils, getFile } from '$lib/db';
import { Group } from 'lucide-svelte';
import { getURLForLanguage } from '$lib/utils';

View File

@@ -10,7 +10,7 @@
} from '$lib/components/file-list/FileList';
import Help from '$lib/components/Help.svelte';
import { Filter } from 'lucide-svelte';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import WithUnits from '$lib/components/WithUnits.svelte';
import { dbUtils, fileObservers } from '$lib/db';
import { map } from '$lib/stores';

View File

@@ -16,7 +16,7 @@
import { CalendarDate, type DateValue } from '@internationalized/date';
import { CalendarClock, CirclePlay, CircleStop, CircleX, Timer, Zap } from 'lucide-svelte';
import { tick } from 'svelte';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { get } from 'svelte/store';
import { selection } from '$lib/components/file-list/Selection';
import {

View File

@@ -12,7 +12,7 @@
import * as Select from '$lib/components/ui/select';
import { selection } from '$lib/components/file-list/Selection';
import { Waypoint } from 'gpx';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { ListWaypointItem } from '$lib/components/file-list/FileList';
import { dbUtils, fileObservers, getFile, settings, type GPXFileWithStatistics } from '$lib/db';
import { get } from 'svelte/store';

View File

@@ -26,7 +26,7 @@
import { dbUtils, getFile, getFileIds, settings } from '$lib/db';
import { brouterProfiles, routingProfileSelectItem } from './Routing';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { RoutingControls } from './RoutingControls';
import mapboxgl from 'mapbox-gl';
import { fileObservers } from '$lib/db';

View File

@@ -2,7 +2,7 @@ import type { Coordinates } from 'gpx';
import { TrackPoint, distance } from 'gpx';
import { derived, get, writable } from 'svelte/store';
import { settings } from '$lib/db';
import { _, isLoading, locale } from 'svelte-i18n';
import { _, locale, isLoadingLocale } from '$lib/i18n';
import { getElevation } from '$lib/utils';
const { routing, routingProfile, privateRoads } = settings;
@@ -22,7 +22,7 @@ export const routingProfileSelectItem = writable({
label: '',
});
derived([routingProfile, locale, isLoading], ([profile, l, i]) => [profile, l, i]).subscribe(
derived([routingProfile, locale, isLoadingLocale], ([profile, l, i]) => [profile, l, i]).subscribe(
([profile, l, i]) => {
if (
!i &&

View File

@@ -5,7 +5,7 @@
import { canChangeStart } from './RoutingControls';
import { CirclePlay, Trash2 } from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
export let element: HTMLElement;
</script>

View File

@@ -3,7 +3,7 @@ import { get, writable, type Readable } from 'svelte/store';
import mapboxgl from 'mapbox-gl';
import { route } from './Routing';
import { toast } from 'svelte-sonner';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { dbUtils, settings, type GPXFileWithStatistics } from '$lib/db';
import { getOrderedSelection, selection } from '$lib/components/file-list/Selection';
import {

View File

@@ -17,7 +17,7 @@
import { Separator } from '$lib/components/ui/separator';
import { gpxStatistics, map, slicedGPXStatistics, splitAs } from '$lib/stores';
import { get } from 'svelte/store';
import { _, locale } from 'svelte-i18n';
import { _, locale } from '$lib/i18n';
import { onDestroy, tick } from 'svelte';
import { Crop } from 'lucide-svelte';
import { dbUtils } from '$lib/db';

View File

@@ -8,7 +8,7 @@ import {
} from '$lib/components/file-list/Selection';
import { ListTrackSegmentItem } from '$lib/components/file-list/FileList';
import { currentTool, gpxStatistics, Tool } from '$lib/stores';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import { Scissors } from 'lucide-static';
export class SplitControls {

56
website/src/lib/i18n.ts Normal file
View File

@@ -0,0 +1,56 @@
import { derived, writable, get } from 'svelte/store';
export const locale = writable('');
type Dictionary = {
[key: string]: string | Dictionary;
};
export const dictionary = writable<Dictionary>({});
export const isLoadingInitialLocale = writable<boolean>(true);
export const isLoadingLocale = writable<boolean>(true);
locale.subscribe((lang) => {
if (lang !== '') {
if (!get(isLoadingLocale)) {
isLoadingLocale.set(true);
}
import(`../locales/${lang}.json`).then((module) => {
dictionary.set(module.default);
if (get(isLoadingInitialLocale)) {
isLoadingInitialLocale.set(false);
}
if (get(isLoadingLocale)) {
isLoadingLocale.set(false);
}
});
}
});
export const _ = derived(dictionary, ($dictionary) => {
return (key: string) => {
const keys = key.split('.');
let value: string | Dictionary = $dictionary;
for (const k of keys) {
if (value && typeof value === 'object' && k in value) {
value = value[k];
} else {
return key;
}
}
return typeof value === 'string' ? value : key;
};
});
function getDateFormatter(locale: string) {
return new Intl.DateTimeFormat(locale, {
dateStyle: 'medium',
timeStyle: 'medium',
});
}
export const df = derived(locale, ($locale) => {
return getDateFormatter($locale === '' ? 'en-US' : $locale);
});

View File

@@ -3,7 +3,7 @@ import { writable, get, type Writable, derived } from 'svelte/store';
import mapboxgl from 'mapbox-gl';
import { GPXFile, buildGPX, parseGPX, GPXStatistics, type Coordinates } from 'gpx';
import { tick } from 'svelte';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
import type { GPXLayer } from '$lib/components/gpx-layer/GPXLayer';
import { dbUtils, fileObservers, getFile, getStatistics, settings } from './db';
import {

View File

@@ -1,6 +1,6 @@
import { get } from 'svelte/store';
import { settings } from '$lib/db';
import { _ } from 'svelte-i18n';
import { _ } from '$lib/i18n';
const { distanceUnits, velocityUnits, temperatureUnits } = settings;

View File

@@ -6,13 +6,11 @@ import { get } from 'svelte/store';
import { map } from './stores';
import { base } from '$app/paths';
import { languages } from '$lib/languages';
import { locale } from 'svelte-i18n';
import { TrackPoint, Waypoint, type Coordinates, crossarcDistance, distance } from 'gpx';
import mapboxgl from 'mapbox-gl';
import tilebelt from '@mapbox/tilebelt';
import { PUBLIC_MAPBOX_TOKEN } from '$env/static/public';
import PNGReader from 'png.js';
import type { DateFormatter } from '@internationalized/date';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
@@ -219,7 +217,7 @@ export function isSafari() {
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
}
export function getURLForLanguage(lang: string | null | undefined, path: string): string {
export function getURLForLanguage(lang: string, path: string): string {
let newPath = path.replace(base, '');
let languageInPath = newPath.split('/')[1];
@@ -227,13 +225,6 @@ export function getURLForLanguage(lang: string | null | undefined, path: string)
languageInPath = 'en';
}
if (lang === null || lang === undefined) {
lang = get(locale);
if (lang === null || lang === undefined) {
lang = 'en';
}
}
if (newPath === '/' && lang !== 'en') {
newPath = '';
}
@@ -254,15 +245,3 @@ export function getURLForLanguage(lang: string | null | undefined, path: string)
}
}
}
function getDateFormatter(locale: string) {
return new Intl.DateTimeFormat(locale, {
dateStyle: 'medium',
timeStyle: 'medium',
});
}
export let df: DateFormatter = getDateFormatter('en');
locale.subscribe((l) => {
df = getDateFormatter(l ?? 'en');
});