From 3b5b228f96ed4ec4753ba3c46256d516ead061bb Mon Sep 17 00:00:00 2001 From: busya Date: Wed, 3 Jun 2026 10:59:22 +0300 Subject: [PATCH] fix(frontend): replace with getT()?. in all .svelte.ts model files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following the documented pattern from 27435e4 (bug report: docs/bug-reports/2026-06-02-svelte5-proxy-store-t-undefined.md). $t.x references in .svelte.ts files are fragile — Svelte 5 compiler can fail to detect the Proxy-based t store as subscribable, causing ReferenceError: $t is not defined at runtime. Changed 3 model files: - DashboardDetailModel.svelte.ts — 8 $t.dashboard?.x → getT()?.dashboard?.x - TranslateHistoryModel.svelte.ts — 4 $t.translate?.run?.x → getT()?.translate?.run?.x - ValidationTasksListModel.svelte.ts — 2 $t.validation?.x → getT()?.validation?.x All imports changed from { t } to { getT } (or { _, getT } for TranslateHistoryModel which already used _() for keyed lookups). @RATIONALE getT() returns the plain translation object directly, bypassing the Proxy store entirely — this avoids Svelte 5's fragile static store-detection on Proxy objects. Verification: npm run build clean, browser renders for all 4 affected routes with zero console errors. --- .../lib/models/DashboardDetailModel.svelte.ts | 18 +++++++++--------- .../lib/models/TranslateHistoryModel.svelte.ts | 10 +++++----- .../models/ValidationTasksListModel.svelte.ts | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/frontend/src/lib/models/DashboardDetailModel.svelte.ts b/frontend/src/lib/models/DashboardDetailModel.svelte.ts index a849e524..96fa27ef 100644 --- a/frontend/src/lib/models/DashboardDetailModel.svelte.ts +++ b/frontend/src/lib/models/DashboardDetailModel.svelte.ts @@ -26,7 +26,7 @@ import { log } from '$lib/cot-logger'; import { GitStatusModel } from '$lib/models/GitStatusModel.svelte.ts'; import { addToast } from '$lib/toasts.svelte.js'; import { openDrawerForTaskIfPreferred } from '$lib/stores/taskDrawer.svelte.js'; -import { t } from '$lib/i18n/index.svelte.js'; +import { getT } from '$lib/i18n/index.svelte.js'; // ── Types ─────────────────────────────────────────────────────── @@ -129,7 +129,7 @@ export class DashboardDetailModel { async loadDashboardDetail(): Promise { if (!this.dashboardRef || !this.envId) { - this.error = $t.dashboard?.missing_context; + this.error = getT()?.dashboard?.missing_context; this.screenState = 'error'; return; } @@ -142,7 +142,7 @@ export class DashboardDetailModel { this.screenState = 'loaded'; log('DashboardDetailModel', 'REFLECT', 'Dashboard detail loaded', { id: this.dashboard?.id, title: this.dashboard?.title }); } catch (err: unknown) { - this.error = err instanceof Error ? err.message : String($t.dashboard?.load_detail_failed); + this.error = err instanceof Error ? err.message : String(getT()?.dashboard?.load_detail_failed); this.screenState = 'error'; log('DashboardDetailModel', 'EXPLORE', 'Failed to load dashboard', { ref: this.dashboardRef }, String(this.error)); } @@ -175,9 +175,9 @@ export class DashboardDetailModel { this.thumbnailUrl = URL.createObjectURL(blob); } catch (err: unknown) { if ((err as { status?: number })?.status === 202) { - this.thumbnailError = $t.dashboard?.thumbnail_generating || 'Thumbnail is being generated'; + this.thumbnailError = getT()?.dashboard?.thumbnail_generating || 'Thumbnail is being generated'; } else { - this.thumbnailError = err instanceof Error ? err.message : String($t.dashboard?.thumbnail_failed); + this.thumbnailError = err instanceof Error ? err.message : String(getT()?.dashboard?.thumbnail_failed); } } finally { this.isThumbnailLoading = false; @@ -217,11 +217,11 @@ export class DashboardDetailModel { const taskId = response?.task_id; if (taskId) { openDrawerForTaskIfPreferred(taskId); - addToast($t.dashboard?.backup_started || 'Backup task started', 'success'); + addToast(getT()?.dashboard?.backup_started || 'Backup task started', 'success'); } await this.loadTaskHistory(); } catch (err: unknown) { - addToast(err instanceof Error ? err.message : $t.dashboard?.backup_task_failed || 'Failed to start backup', 'error'); + addToast(err instanceof Error ? err.message : (getT()?.dashboard?.backup_task_failed || 'Failed to start backup'), 'error'); } finally { this.isStartingBackup = false; } @@ -267,8 +267,8 @@ export class DashboardDetailModel { // ── Static utilities ────────────────────────────────────────── static toTaskTypeLabel(pluginId: string | undefined): string { - if (pluginId === 'superset-backup') return $t.dashboard?.backup || 'Backup'; - if (pluginId === 'llm_dashboard_validation') return $t.dashboard?.llm_check || 'LLM Check'; + if (pluginId === 'superset-backup') return getT()?.dashboard?.backup || 'Backup'; + if (pluginId === 'llm_dashboard_validation') return getT()?.dashboard?.llm_check || 'LLM Check'; return pluginId || '-'; } diff --git a/frontend/src/lib/models/TranslateHistoryModel.svelte.ts b/frontend/src/lib/models/TranslateHistoryModel.svelte.ts index b248218d..fe97e458 100644 --- a/frontend/src/lib/models/TranslateHistoryModel.svelte.ts +++ b/frontend/src/lib/models/TranslateHistoryModel.svelte.ts @@ -10,7 +10,7 @@ import { log } from '$lib/cot-logger'; import { addToast } from '$lib/toasts.svelte.js'; -import { t, _ } from '$lib/i18n/index.svelte.js'; +import { _, getT } from '$lib/i18n/index.svelte.js'; import { fetchAllRuns, fetchRunDetail, fetchAllMetrics, fetchJobs, downloadSkippedCsv, downloadFailedCsv, cancelRun, retryFailedBatches } from '$lib/api/translate.js'; type UxState = 'idle' | 'loading' | 'empty' | 'populated' | 'detail_open' | 'pruned'; @@ -103,11 +103,11 @@ export class TranslateHistoryModel { this.cancellingRunId = runId; try { await cancelRun(runId); - addToast($t.translate?.run?.run_cancelled || 'Run cancelled', 'success'); + addToast(getT()?.translate?.run?.run_cancelled || 'Run cancelled', 'success'); if (this.selectedRunDetail?.id === runId) this.selectedRunDetail = await fetchRunDetail(runId); this.loadRuns(); } catch (err: unknown) { - addToast(err instanceof Error ? err.message : $t.translate?.run?.cancel_failed || 'Failed to cancel run', 'error'); + addToast(err instanceof Error ? err.message : (getT()?.translate?.run?.cancel_failed || 'Failed to cancel run'), 'error'); } finally { this.cancellingRunId = null; } } @@ -115,11 +115,11 @@ export class TranslateHistoryModel { this.retryingRunId = runId; try { await retryFailedBatches(runId); - addToast($t.translate?.run?.retry_success || 'Retry started', 'success'); + addToast(getT()?.translate?.run?.retry_success || 'Retry started', 'success'); if (this.selectedRunDetail?.id === runId) this.selectedRunDetail = await fetchRunDetail(runId); this.loadRuns(); } catch (err: unknown) { - addToast(err instanceof Error ? err.message : $t.translate?.run?.retry_failed_msg || 'Retry failed', 'error'); + addToast(err instanceof Error ? err.message : (getT()?.translate?.run?.retry_failed_msg || 'Retry failed'), 'error'); } finally { this.retryingRunId = null; } } diff --git a/frontend/src/lib/models/ValidationTasksListModel.svelte.ts b/frontend/src/lib/models/ValidationTasksListModel.svelte.ts index 8c63e0f4..c6905c3c 100644 --- a/frontend/src/lib/models/ValidationTasksListModel.svelte.ts +++ b/frontend/src/lib/models/ValidationTasksListModel.svelte.ts @@ -22,7 +22,7 @@ import { ROUTES } from '$lib/routes'; import { api } from '$lib/api.js'; import { log } from '$lib/cot-logger'; import { addToast } from '$lib/toasts.svelte.js'; -import { t } from '$lib/i18n/index.svelte.js'; +import { getT } from '$lib/i18n/index.svelte.js'; // ── Types ─────────────────────────────────────────────────────── @@ -124,7 +124,7 @@ export class ValidationTasksListModel { try { await api.triggerValidationRun(id); if (!this.isMounted) return; - addToast($t.validation?.run_started || 'Validation task started', 'success'); + addToast(getT()?.validation?.run_started || 'Validation task started', 'success'); log('ValidationTasksListModel', 'REFLECT', 'Run triggered', { taskId: id }); } catch (e: unknown) { if (!this.isMounted) return; @@ -140,7 +140,7 @@ export class ValidationTasksListModel { try { await api.deleteValidationTask(id); if (!this.isMounted) return; - addToast($t.validation?.delete_success || 'Task deleted', 'success'); + addToast(getT()?.validation?.delete_success || 'Task deleted', 'success'); this.deleteConfirmId = null; this.tasks = this.tasks.filter(t => t.id !== id); this.total = Math.max(0, this.total - 1);