diff --git a/website/src/lib/engine/backend/index.ts b/website/src/lib/engine/backend/index.ts index 6807e44d0..fb4cbc6a1 100644 --- a/website/src/lib/engine/backend/index.ts +++ b/website/src/lib/engine/backend/index.ts @@ -3,7 +3,7 @@ import type { Backend } from './types'; export type { Backend } from './types'; /** Whether the page runs in the desktop app, which has the engine in its own process. */ -function inDesktopApp() { +export function inDesktopApp() { return typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window; } diff --git a/website/src/lib/state/settings.ts b/website/src/lib/state/settings.ts index 07778f9ea..c198dc128 100644 --- a/website/src/lib/state/settings.ts +++ b/website/src/lib/state/settings.ts @@ -15,6 +15,7 @@ import { import { browser } from '$app/environment'; import type { DistanceUnits, TemperatureUnits, VelocityUnits } from '$lib/units/conversions'; import { engine } from '$lib/engine'; +import { languages } from '$lib/i18n/languages'; import { getArrayValidator, getLayerTreeValidator, @@ -157,6 +158,12 @@ export const settings = { bottomPanelSize: new Setting('bottomPanelSize', 170), rightPanelSize: new Setting('rightPanelSize', 240), explorerPanelSize: new Setting('explorerPanelSize', 0), + /** The language chosen last, for the desktop app, which always opens the same page. */ + language: new Setting( + 'language', + undefined, + getValueValidator(Object.keys(languages), undefined) + ), /** Takes the saved values (see `Engine.openStorage`). */ connect(stored: StoredSettings) { for (const key in settings) { diff --git a/website/src/routes/[[language]]/app/+page.svelte b/website/src/routes/[[language]]/app/+page.svelte index 5bb53edd3..dcd2c9313 100644 --- a/website/src/routes/[[language]]/app/+page.svelte +++ b/website/src/routes/[[language]]/app/+page.svelte @@ -18,6 +18,10 @@ import { loadFiles } from '$lib/actions/file-actions'; import { onMount } from 'svelte'; import { page } from '$app/state'; + import { goto } from '$app/navigation'; + import { get } from 'svelte/store'; + import { getURLForLanguage } from '$lib/utils'; + import { inDesktopApp } from '$lib/engine/backend'; import { hoveredPoint, slicedStatistics } from '$lib/state/selection-statistics'; import { engine } from '$lib/engine'; import { boundsManager } from '$lib/state/bounds'; @@ -51,11 +55,35 @@ bottomPanelWidth && bottomPanelWidth >= 540 && $elevationProfile ? 'horizontal' : 'vertical' ); + // the language of the page, which is in its address (none for English) + let language = $derived(page.params.language ?? 'en'); + // whether the language that was chosen last was gone back to (the desktop app) + let languageRestored = $state(false); + + $effect(() => { + if (languageRestored) { + settings.language.set(language); + } + }); + onMount(async () => { // files that the system opens with the app while it runs engine.onFilesOpened((ids) => boundsManager.fitBoundsOnLoad(ids)); settings.connect(await engine.openStorage()); + if (inDesktopApp()) { + // the window of the desktop app always opens the same page, in English: it goes to the + // language that was chosen last + const saved = get(settings.language); + if (saved !== undefined && saved !== language) { + await goto( + `${getURLForLanguage(saved, page.url.pathname)}${page.url.search}${page.url.hash}`, + { replaceState: true } + ); + } + languageRestored = true; + } + let files: string[] = JSON.parse(page.url.searchParams.get('files') || '[]'); let ids: string[] = JSON.parse(page.url.searchParams.get('ids') || '[]'); let urls: string[] = files.concat(ids.map(getURLForGoogleDriveFile));