fix(frontend): replace with getT()?. in all .svelte.ts model files

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.
This commit is contained in:
2026-06-03 10:59:22 +03:00
parent b5e104c9e8
commit 3b5b228f96
3 changed files with 17 additions and 17 deletions

View File

@@ -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<void> {
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 || '-';
}

View File

@@ -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; }
}

View File

@@ -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);