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:
@@ -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 || '-';
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user