i18 cleanup
This commit is contained in:
@@ -260,8 +260,8 @@
|
||||
|
||||
function buildConversationTitle(conversation) {
|
||||
if (conversation?.title?.trim()) return conversation.title.trim();
|
||||
if (!conversation?.conversation_id) return "Conversation";
|
||||
return `Conversation ${conversation.conversation_id.slice(0, 8)}`;
|
||||
if (!conversation?.conversation_id) return $t.assistant?.conversation;
|
||||
return `${$t.assistant?.conversation} ${conversation.conversation_id.slice(0, 8)}`;
|
||||
}
|
||||
|
||||
function setConversationFilter(filter) {
|
||||
@@ -312,7 +312,7 @@
|
||||
} catch (err) {
|
||||
appendAssistantResponse({
|
||||
response_id: `error-${Date.now()}`,
|
||||
text: err.message || "Assistant request failed",
|
||||
text: err.message || $t.assistant?.request_failed,
|
||||
state: "failed",
|
||||
created_at: new Date().toISOString(),
|
||||
actions: [],
|
||||
@@ -402,7 +402,7 @@
|
||||
} catch (err) {
|
||||
appendAssistantResponse({
|
||||
response_id: `action-error-${Date.now()}`,
|
||||
text: err.message || "Action failed",
|
||||
text: err.message || $t.assistant?.action_failed,
|
||||
state: "failed",
|
||||
created_at: new Date().toISOString(),
|
||||
actions: [],
|
||||
@@ -484,13 +484,13 @@
|
||||
<div class="flex items-center gap-2 text-slate-800">
|
||||
<Icon name="clipboard" size={18} />
|
||||
<h2 class="text-sm font-semibold">
|
||||
{$t.assistant?.title || "AI Assistant"}
|
||||
{$t.assistant?.title}
|
||||
</h2>
|
||||
</div>
|
||||
<button
|
||||
class="rounded-md p-1 text-slate-500 transition hover:bg-slate-100 hover:text-slate-900"
|
||||
on:click={closeAssistantChat}
|
||||
aria-label={$t.assistant?.close || "Close assistant"}
|
||||
aria-label={$t.assistant?.close}
|
||||
>
|
||||
<Icon name="close" size={18} />
|
||||
</button>
|
||||
@@ -501,13 +501,13 @@
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<span
|
||||
class="text-xs font-semibold uppercase tracking-wide text-slate-500"
|
||||
>Conversations</span
|
||||
>{$t.assistant?.conversations}</span
|
||||
>
|
||||
<button
|
||||
class="rounded-md border border-slate-300 px-2 py-1 text-[11px] font-medium text-slate-700 transition hover:bg-slate-100"
|
||||
on:click={startNewConversation}
|
||||
>
|
||||
New
|
||||
{$t.assistant?.new}
|
||||
</button>
|
||||
</div>
|
||||
<div class="mb-2 flex items-center gap-1">
|
||||
@@ -518,7 +518,7 @@
|
||||
: 'border-slate-300 bg-white text-slate-700 hover:bg-slate-100'}"
|
||||
on:click={() => setConversationFilter("active")}
|
||||
>
|
||||
Active ({activeConversationsTotal})
|
||||
{$t.assistant?.active} ({activeConversationsTotal})
|
||||
</button>
|
||||
<button
|
||||
class="rounded-md border px-2 py-1 text-[11px] font-medium transition {conversationFilter ===
|
||||
@@ -527,7 +527,7 @@
|
||||
: 'border-slate-300 bg-white text-slate-700 hover:bg-slate-100'}"
|
||||
on:click={() => setConversationFilter("archived")}
|
||||
>
|
||||
Archived ({archivedConversationsTotal})
|
||||
{$t.assistant?.archived} ({archivedConversationsTotal})
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex gap-2 overflow-x-auto pb-1">
|
||||
@@ -560,7 +560,7 @@
|
||||
class="rounded-lg border border-slate-300 px-2.5 py-1.5 text-xs font-medium text-slate-700 transition hover:bg-slate-100"
|
||||
on:click={() => loadConversations(false)}
|
||||
>
|
||||
More
|
||||
{$t.assistant?.more}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -575,24 +575,24 @@
|
||||
<div
|
||||
class="rounded-lg border border-slate-200 bg-slate-50 p-2 text-center text-xs text-slate-500"
|
||||
>
|
||||
Loading older messages...
|
||||
{$t.assistant?.loading_older}
|
||||
</div>
|
||||
{/if}
|
||||
{#if loadingHistory}
|
||||
<div
|
||||
class="rounded-lg border border-slate-200 bg-slate-50 p-3 text-sm text-slate-600"
|
||||
>
|
||||
{$t.assistant?.loading_history || "Loading history..."}
|
||||
{$t.assistant?.loading_history}
|
||||
</div>
|
||||
{:else if messages.length === 0}
|
||||
<div
|
||||
class="rounded-lg border border-slate-200 bg-slate-50 p-3 text-sm text-slate-600"
|
||||
>
|
||||
{$t.assistant?.try_commands || "Try commands:"}
|
||||
{$t.assistant?.try_commands}
|
||||
<div class="mt-2 space-y-1 text-xs">
|
||||
<div>• сделай ветку feature/new-dashboard для дашборда 42</div>
|
||||
<div>• запусти миграцию с dev на prod для дашборда 42</div>
|
||||
<div>• проверь статус задачи task-123</div>
|
||||
<div>• {$t.assistant?.sample_command_branch}</div>
|
||||
<div>• {$t.assistant?.sample_command_migration}</div>
|
||||
<div>• {$t.assistant?.sample_command_status}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -608,7 +608,7 @@
|
||||
<span
|
||||
class="text-[11px] font-semibold uppercase tracking-wide text-slate-500"
|
||||
>
|
||||
{message.role === "user" ? "You" : "Assistant"}
|
||||
{message.role === "user" ? $t.assistant?.you : $t.assistant?.assistant}
|
||||
</span>
|
||||
{#if message.state}
|
||||
<span
|
||||
@@ -629,13 +629,13 @@
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<span
|
||||
class="rounded border border-slate-200 bg-slate-50 px-2 py-0.5 text-xs text-slate-700"
|
||||
>task_id: {message.task_id}</span
|
||||
>{$t.assistant?.task_id}: {message.task_id}</span
|
||||
>
|
||||
<button
|
||||
class="text-xs font-medium text-sky-700 hover:text-sky-900"
|
||||
on:click={() => openDrawerForTask(message.task_id)}
|
||||
>
|
||||
{$t.assistant?.open_task_drawer || "Open Task Drawer"}
|
||||
{$t.assistant?.open_task_drawer}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -668,11 +668,11 @@
|
||||
<span
|
||||
class="text-[11px] font-semibold uppercase tracking-wide text-slate-500"
|
||||
>
|
||||
Assistant
|
||||
{$t.assistant?.assistant}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 text-sm text-slate-700">
|
||||
<span>{$t.assistant?.thinking || "Думаю"}</span>
|
||||
<span>{$t.assistant?.thinking}</span>
|
||||
<span class="thinking-dots" aria-hidden="true">
|
||||
<span></span><span></span><span></span>
|
||||
</span>
|
||||
@@ -687,7 +687,7 @@
|
||||
<textarea
|
||||
bind:value={input}
|
||||
rows="2"
|
||||
placeholder={$t.assistant?.input_placeholder || "Type a command..."}
|
||||
placeholder={$t.assistant?.input_placeholder}
|
||||
class="min-h-[52px] w-full resize-y rounded-lg border border-slate-300 px-3 py-2 text-sm outline-none transition focus:border-sky-400 focus:ring-2 focus:ring-sky-100"
|
||||
on:keydown={handleKeydown}
|
||||
></textarea>
|
||||
@@ -696,7 +696,7 @@
|
||||
on:click={handleSend}
|
||||
disabled={loading || !input.trim()}
|
||||
>
|
||||
{loading ? "..." : $t.assistant?.send || "Send"}
|
||||
{loading ? "..." : $t.assistant?.send}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
*/
|
||||
function getBreadcrumbs(pathname, maxVisible = 3) {
|
||||
const segments = pathname.split("/").filter(Boolean);
|
||||
const allItems = [{ label: $t.nav?.home || "Home", path: "/" }];
|
||||
const allItems = [{ label: $t.nav?.home , path: "/" }];
|
||||
|
||||
let currentPath = "";
|
||||
segments.forEach((segment, index) => {
|
||||
@@ -136,7 +136,7 @@
|
||||
|
||||
<nav
|
||||
class="mx-4 md:mx-6"
|
||||
aria-label={$t.nav?.breadcrumb_nav || "Breadcrumb navigation"}
|
||||
aria-label={$t.nav?.breadcrumb_nav }
|
||||
>
|
||||
<div class="inline-flex max-w-full items-center gap-1.5 rounded-xl border border-slate-200/80 bg-white/85 px-2 py-1.5 shadow-sm backdrop-blur">
|
||||
{#each breadcrumbItems as item, index}
|
||||
|
||||
@@ -30,56 +30,56 @@
|
||||
return [
|
||||
{
|
||||
id: "dashboards",
|
||||
label: $t.nav?.dashboards || "DASHBOARDS",
|
||||
label: $t.nav?.dashboards ,
|
||||
icon: "dashboard",
|
||||
tone: "from-sky-100 to-sky-200 text-sky-700 ring-sky-200",
|
||||
path: "/dashboards",
|
||||
subItems: [
|
||||
{ label: $t.nav?.overview || "Overview", path: "/dashboards" },
|
||||
{ label: $t.nav?.overview , path: "/dashboards" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "datasets",
|
||||
label: $t.nav?.datasets || "DATASETS",
|
||||
label: $t.nav?.datasets ,
|
||||
icon: "database",
|
||||
tone: "from-emerald-100 to-emerald-200 text-emerald-700 ring-emerald-200",
|
||||
path: "/datasets",
|
||||
subItems: [
|
||||
{ label: $t.nav?.all_datasets || "All Datasets", path: "/datasets" },
|
||||
{ label: $t.nav?.all_datasets , path: "/datasets" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "storage",
|
||||
label: $t.nav?.storage || "STORAGE",
|
||||
label: $t.nav?.storage ,
|
||||
icon: "storage",
|
||||
tone: "from-amber-100 to-amber-200 text-amber-800 ring-amber-200",
|
||||
path: "/storage",
|
||||
subItems: [
|
||||
{ label: $t.nav?.backups || "Backups", path: "/storage/backups" },
|
||||
{ label: $t.nav?.backups , path: "/storage/backups" },
|
||||
{
|
||||
label: $t.nav?.repositories || "Repositories",
|
||||
label: $t.nav?.repositories ,
|
||||
path: "/storage/repos",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "reports",
|
||||
label: $t.nav?.reports || "REPORTS",
|
||||
label: $t.nav?.reports ,
|
||||
icon: "reports",
|
||||
tone: "from-violet-100 to-fuchsia-100 text-violet-700 ring-violet-200",
|
||||
path: "/reports",
|
||||
subItems: [{ label: $t.nav?.reports || "Reports", path: "/reports" }],
|
||||
subItems: [{ label: $t.nav?.reports , path: "/reports" }],
|
||||
},
|
||||
{
|
||||
id: "admin",
|
||||
label: $t.nav?.admin || "ADMIN",
|
||||
label: $t.nav?.admin ,
|
||||
icon: "admin",
|
||||
tone: "from-rose-100 to-rose-200 text-rose-700 ring-rose-200",
|
||||
path: "/admin",
|
||||
subItems: [
|
||||
{ label: $t.nav?.admin_users || "Users", path: "/admin/users" },
|
||||
{ label: $t.nav?.admin_roles || "Roles", path: "/admin/roles" },
|
||||
{ label: $t.nav?.settings || "Settings", path: "/settings" },
|
||||
{ label: $t.nav?.admin_users , path: "/admin/users" },
|
||||
{ label: $t.nav?.admin_roles , path: "/admin/roles" },
|
||||
{ label: $t.nav?.settings , path: "/settings" },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -201,7 +201,7 @@
|
||||
<span class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br from-slate-100 to-slate-200 text-slate-700 ring-1 ring-slate-200">
|
||||
<Icon name="layers" size={14} />
|
||||
</span>
|
||||
{$t.nav?.menu || "Menu"}
|
||||
{$t.nav?.menu }
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-xs text-gray-500">M</span>
|
||||
@@ -285,7 +285,7 @@
|
||||
<span class="mr-2 inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-100 text-slate-600">
|
||||
<Icon name="chevronLeft" size={14} />
|
||||
</span>
|
||||
{$t.nav?.collapse || "Collapse"}
|
||||
{$t.nav?.collapse }
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
@@ -293,10 +293,10 @@
|
||||
<button
|
||||
class="flex items-center justify-center w-full px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
on:click={handleToggleClick}
|
||||
aria-label={$t.nav?.expand_sidebar || "Expand sidebar"}
|
||||
aria-label={$t.nav?.expand_sidebar }
|
||||
>
|
||||
<Icon name="chevronRight" size={16} />
|
||||
<span class="ml-2">{$t.nav?.expand || "Expand"}</span>
|
||||
<span class="ml-2">{$t.nav?.expand }</span>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
style={`right: ${assistantOffset};`}
|
||||
role="dialog"
|
||||
aria-modal="false"
|
||||
aria-label={$t.tasks?.drawer || "Task drawer"}
|
||||
aria-label={$t.tasks?.drawer }
|
||||
>
|
||||
<!-- Header -->
|
||||
<div
|
||||
@@ -237,15 +237,15 @@
|
||||
<button
|
||||
class="flex items-center justify-center p-1.5 rounded-md text-slate-500 bg-transparent border-none cursor-pointer transition-all hover:text-slate-100 hover:bg-slate-800"
|
||||
on:click={goBackToList}
|
||||
aria-label={$t.tasks?.back_to_list || "Back to task list"}
|
||||
aria-label={$t.tasks?.back_to_list }
|
||||
>
|
||||
<Icon name="back" size={16} strokeWidth={2} />
|
||||
</button>
|
||||
{/if}
|
||||
<h2 class="text-sm font-semibold tracking-tight text-slate-900">
|
||||
{activeTaskId
|
||||
? $t.tasks?.details_logs || "Task Details & Logs"
|
||||
: $t.tasks?.recent || "Recent Tasks"}
|
||||
? $t.tasks?.details_logs
|
||||
: $t.tasks?.recent }
|
||||
</h2>
|
||||
{#if shortTaskId}
|
||||
<span
|
||||
@@ -270,12 +270,12 @@
|
||||
class="rounded-md border border-slate-300 bg-slate-50 px-2.5 py-1 text-xs font-semibold text-slate-700 transition-colors hover:bg-slate-100"
|
||||
on:click={goToReportsPage}
|
||||
>
|
||||
{$t.nav?.reports || "Reports"}
|
||||
{$t.nav?.reports }
|
||||
</button>
|
||||
<button
|
||||
class="p-1.5 rounded-md text-slate-500 bg-transparent border-none cursor-pointer transition-all hover:text-slate-100 hover:bg-slate-800"
|
||||
on:click={handleClose}
|
||||
aria-label={$t.tasks?.close_drawer || "Close drawer"}
|
||||
aria-label={$t.tasks?.close_drawer }
|
||||
>
|
||||
<Icon name="close" size={18} strokeWidth={2} />
|
||||
</button>
|
||||
@@ -298,14 +298,14 @@
|
||||
<div
|
||||
class="mb-4 h-8 w-8 animate-spin rounded-full border-2 border-slate-200 border-t-blue-500"
|
||||
></div>
|
||||
<p>{$t.tasks?.loading || "Loading tasks..."}</p>
|
||||
<p>{$t.tasks?.loading }</p>
|
||||
</div>
|
||||
{:else if recentTasks.length > 0}
|
||||
<div class="p-4">
|
||||
<h3
|
||||
class="text-sm font-semibold text-slate-100 mb-4 pb-2 border-b border-slate-800"
|
||||
>
|
||||
{$t.tasks?.recent || "Recent Tasks"}
|
||||
{$t.tasks?.recent }
|
||||
</h3>
|
||||
{#each recentTasks as task}
|
||||
<button
|
||||
@@ -318,7 +318,7 @@
|
||||
"N/A"}...</span
|
||||
>
|
||||
<span class="flex-1 text-sm text-slate-100 font-medium"
|
||||
>{task.plugin_id || $t.common?.unknown || "Unknown"}</span
|
||||
>{task.plugin_id || $t.common?.unknown }</span
|
||||
>
|
||||
<span
|
||||
class="text-xs font-semibold uppercase px-2 py-1 rounded-full {task.status?.toLowerCase() ===
|
||||
@@ -331,7 +331,7 @@
|
||||
task.status?.toLowerCase() === 'error'
|
||||
? 'bg-red-500/15 text-red-400'
|
||||
: 'bg-slate-500/15 text-slate-400'}"
|
||||
>{task.status || $t.common?.unknown || "UNKNOWN"}</span
|
||||
>{task.status || $t.common?.unknown }</span
|
||||
>
|
||||
</button>
|
||||
{/each}
|
||||
@@ -346,7 +346,7 @@
|
||||
strokeWidth={1.6}
|
||||
className="mb-3 text-slate-700"
|
||||
/>
|
||||
<p>{$t.tasks?.select_task || "No recent tasks"}</p>
|
||||
<p>{$t.tasks?.select_task }</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -357,7 +357,7 @@
|
||||
>
|
||||
<div class="w-1.5 h-1.5 rounded-full bg-cyan-400 animate-pulse"></div>
|
||||
<p class="text-xs text-slate-500">
|
||||
{$t.tasks?.footer_text || "Task continues running in background"}
|
||||
{$t.tasks?.footer_text }
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
<button
|
||||
class="rounded-lg p-2 text-slate-600 transition-colors hover:bg-slate-100 md:hidden"
|
||||
on:click={handleHamburgerClick}
|
||||
aria-label={$t.common?.toggle_menu || "Toggle menu"}
|
||||
aria-label={$t.common?.toggle_menu }
|
||||
>
|
||||
<Icon name="menu" size={22} />
|
||||
</button>
|
||||
@@ -119,7 +119,7 @@
|
||||
<span class="mr-2 inline-flex h-9 w-9 items-center justify-center rounded-xl bg-gradient-to-br from-sky-500 via-cyan-500 to-indigo-600 text-white shadow-sm">
|
||||
<Icon name="layers" size={18} strokeWidth={2.1} />
|
||||
</span>
|
||||
<span>Superset Tools</span>
|
||||
<span>{$t.common?.brand }</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
type="text"
|
||||
class="w-full px-4 py-2 bg-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-ring transition-all
|
||||
{isSearchFocused ? 'bg-white border border-primary-ring' : ''}"
|
||||
placeholder={$t.common.search || "Search..."}
|
||||
placeholder={$t.common.search }
|
||||
on:focus={handleSearchFocus}
|
||||
on:blur={handleSearchBlur}
|
||||
/>
|
||||
@@ -143,8 +143,8 @@
|
||||
<button
|
||||
class="rounded-lg p-2 text-slate-600 transition-colors hover:bg-slate-100"
|
||||
on:click={handleAssistantClick}
|
||||
aria-label={$t.assistant?.open || "Open assistant"}
|
||||
title={$t.assistant?.title || "AI Assistant"}
|
||||
aria-label={$t.assistant?.open }
|
||||
title={$t.assistant?.title }
|
||||
>
|
||||
<Icon name="clipboard" size={22} />
|
||||
</button>
|
||||
@@ -157,7 +157,7 @@
|
||||
(e.key === "Enter" || e.key === " ") && handleActivityClick()}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label={$t.common?.activity || "Activity"}
|
||||
aria-label={$t.common?.activity }
|
||||
>
|
||||
<Icon name="activity" size={22} />
|
||||
{#if activeCount > 0}
|
||||
@@ -177,7 +177,7 @@
|
||||
(e.key === "Enter" || e.key === " ") && toggleUserMenu(e)}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label={$t.common?.user_menu || "User menu"}
|
||||
aria-label={$t.common?.user_menu }
|
||||
>
|
||||
{#if user}
|
||||
<span
|
||||
@@ -195,7 +195,7 @@
|
||||
: 'hidden'}"
|
||||
>
|
||||
<div class="px-4 py-2 text-sm text-gray-700">
|
||||
<strong>{user?.username || ($t.common?.user || "User")}</strong>
|
||||
<strong>{user?.username || ($t.common?.user )}</strong>
|
||||
</div>
|
||||
<div class="border-t border-gray-200 my-1"></div>
|
||||
<div
|
||||
@@ -209,7 +209,7 @@
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
{$t.nav?.settings || "Settings"}
|
||||
{$t.nav?.settings }
|
||||
</div>
|
||||
<div
|
||||
class="px-4 py-2 text-sm text-destructive hover:bg-destructive-light cursor-pointer"
|
||||
@@ -219,7 +219,7 @@
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
{$t.common?.logout || "Logout"}
|
||||
{$t.common?.logout }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -32,17 +32,17 @@
|
||||
}
|
||||
|
||||
function getStatusLabel(status) {
|
||||
if (status === 'success') return $t.reports?.status_success || 'Success';
|
||||
if (status === 'failed') return $t.reports?.status_failed || 'Failed';
|
||||
if (status === 'in_progress') return $t.reports?.status_in_progress || 'In progress';
|
||||
if (status === 'partial') return $t.reports?.status_partial || 'Partial';
|
||||
return status || ($t.reports?.not_provided || 'Not provided');
|
||||
if (status === 'success') return $t.reports?.status_success ;
|
||||
if (status === 'failed') return $t.reports?.status_failed ;
|
||||
if (status === 'in_progress') return $t.reports?.status_in_progress ;
|
||||
if (status === 'partial') return $t.reports?.status_partial ;
|
||||
return status || ($t.reports?.not_provided );
|
||||
}
|
||||
|
||||
function formatDate(value) {
|
||||
if (!value) return $t.reports?.not_provided || 'Not provided';
|
||||
if (!value) return $t.reports?.not_provided ;
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) return $t.reports?.not_provided || 'Not provided';
|
||||
if (Number.isNaN(date.getTime())) return $t.reports?.not_provided ;
|
||||
return date.toLocaleString();
|
||||
}
|
||||
|
||||
@@ -54,18 +54,18 @@
|
||||
<button
|
||||
class="w-full rounded-xl border p-4 text-left shadow-sm transition hover:border-slate-300 hover:bg-slate-50 hover:shadow {selected ? 'border-blue-400 bg-blue-50' : 'border-slate-200 bg-white'}"
|
||||
on:click={onSelect}
|
||||
aria-label={`Report ${report?.report_id || ''} type ${profileLabel || ($t.reports?.unknown_type || 'Other / Unknown Type')}`}
|
||||
aria-label={`${$t.reports?.title} ${report?.report_id || ''} ${$t.reports?.type} ${profileLabel || $t.reports?.unknown_type}`}
|
||||
>
|
||||
<div class="mb-2 flex items-center justify-between gap-2">
|
||||
<span class="rounded px-2 py-0.5 text-xs font-semibold {profile?.variant || 'bg-slate-100 text-slate-700'}">
|
||||
{profileLabel || ($t.reports?.unknown_type || 'Other / Unknown Type')}
|
||||
{profileLabel || $t.reports?.unknown_type}
|
||||
</span>
|
||||
<span class="rounded px-2 py-0.5 text-xs font-semibold {getStatusClass(report?.status)}">
|
||||
{getStatusLabel(report?.status)}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-sm font-medium text-slate-800">{report?.summary || ($t.reports?.not_provided || 'Not provided')}</p>
|
||||
<p class="text-sm font-medium text-slate-800">{report?.summary || $t.reports?.not_provided}</p>
|
||||
<p class="mt-1 text-xs text-slate-500">{formatDate(report?.updated_at)}</p>
|
||||
</button>
|
||||
|
||||
<!-- [/DEF:ReportCard:Component] -->
|
||||
<!-- [/DEF:ReportCard:Component] -->
|
||||
|
||||
@@ -18,41 +18,41 @@
|
||||
|
||||
function notProvided(value) {
|
||||
if (value === null || value === undefined || value === '') {
|
||||
return $t.reports?.not_provided || 'Not provided';
|
||||
return $t.reports?.not_provided;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function formatDate(value) {
|
||||
if (!value) return $t.reports?.not_provided || 'Not provided';
|
||||
if (!value) return $t.reports?.not_provided;
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) return $t.reports?.not_provided || 'Not provided';
|
||||
if (Number.isNaN(date.getTime())) return $t.reports?.not_provided;
|
||||
return date.toLocaleString();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-4 shadow-sm">
|
||||
<h3 class="mb-3 text-sm font-semibold text-slate-700">{$t.reports?.view_details || 'View details'}</h3>
|
||||
<h3 class="mb-3 text-sm font-semibold text-slate-700">{$t.reports?.view_details}</h3>
|
||||
|
||||
{#if !detail || !detail.report}
|
||||
<p class="text-sm text-slate-500">{$t.reports?.not_provided || 'Not provided'}</p>
|
||||
<p class="text-sm text-slate-500">{$t.reports?.not_provided}</p>
|
||||
{:else}
|
||||
<div class="space-y-2 text-sm text-slate-700">
|
||||
<p><span class="text-slate-500">ID:</span> {notProvided(detail.report.report_id)}</p>
|
||||
<p><span class="text-slate-500">Type:</span> {notProvided(detail.report.task_type)}</p>
|
||||
<p><span class="text-slate-500">Status:</span> {notProvided(detail.report.status)}</p>
|
||||
<p><span class="text-slate-500">Summary:</span> {notProvided(detail.report.summary)}</p>
|
||||
<p><span class="text-slate-500">Updated:</span> {formatDate(detail.report.updated_at)}</p>
|
||||
<p><span class="text-slate-500">{$t.reports?.id}:</span> {notProvided(detail.report.report_id)}</p>
|
||||
<p><span class="text-slate-500">{$t.reports?.type}:</span> {notProvided(detail.report.task_type)}</p>
|
||||
<p><span class="text-slate-500">{$t.reports?.status}:</span> {notProvided(detail.report.status)}</p>
|
||||
<p><span class="text-slate-500">{$t.reports?.summary}:</span> {notProvided(detail.report.summary)}</p>
|
||||
<p><span class="text-slate-500">{$t.reports?.updated}:</span> {formatDate(detail.report.updated_at)}</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<p class="mb-1 text-xs font-semibold uppercase text-slate-500">{$t.reports?.diagnostics || 'Diagnostics'}</p>
|
||||
<pre class="max-h-48 overflow-auto rounded-lg border border-slate-200 bg-slate-50 p-2 text-xs text-slate-700">{JSON.stringify(detail.diagnostics || { note: $t.reports?.not_provided || 'Not provided' }, null, 2)}</pre>
|
||||
<p class="mb-1 text-xs font-semibold uppercase text-slate-500">{$t.reports?.diagnostics}</p>
|
||||
<pre class="max-h-48 overflow-auto rounded-lg border border-slate-200 bg-slate-50 p-2 text-xs text-slate-700">{JSON.stringify(detail.diagnostics || { note: $t.reports?.not_provided }, null, 2)}</pre>
|
||||
</div>
|
||||
|
||||
{#if (detail.next_actions && detail.next_actions.length > 0) || (detail.report.error_context && detail.report.error_context.next_actions && detail.report.error_context.next_actions.length > 0)}
|
||||
<div class="mt-4">
|
||||
<p class="mb-1 text-xs font-semibold uppercase text-slate-500">{$t.reports?.next_actions || 'Next actions'}</p>
|
||||
<p class="mb-1 text-xs font-semibold uppercase text-slate-500">{$t.reports?.next_actions}</p>
|
||||
<ul class="list-disc space-y-1 pl-5 text-sm text-slate-700">
|
||||
{#each (detail.next_actions && detail.next_actions.length > 0 ? detail.next_actions : detail.report.error_context.next_actions) as action}
|
||||
<li>{action}</li>
|
||||
@@ -63,4 +63,4 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- [/DEF:ReportDetailPanel:Component] -->
|
||||
<!-- [/DEF:ReportDetailPanel:Component] -->
|
||||
|
||||
@@ -19,12 +19,19 @@
|
||||
"activity": "Activity",
|
||||
"user_menu": "User menu",
|
||||
"user": "User",
|
||||
"brand": "Superset Tools",
|
||||
"unknown": "Unknown",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"not_available": "N/A",
|
||||
"first": "First",
|
||||
"last": "Last",
|
||||
"on": "On",
|
||||
"off": "Off",
|
||||
"per_page": "per page",
|
||||
"close_modal": "Close modal"
|
||||
,
|
||||
"choose_environment": "-- Choose an environment --"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Home",
|
||||
@@ -88,12 +95,16 @@
|
||||
"dataset_desc": "Dataset Description",
|
||||
"column_doc": "Column Documentation",
|
||||
"apply_doc": "Apply Documentation",
|
||||
"applying": "Applying..."
|
||||
"applying": "Applying...",
|
||||
"validation_report_title": "Validation Report",
|
||||
"no_validation_result": "No validation result available."
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"language": "Language",
|
||||
"appearance": "Appearance",
|
||||
"llm": "LLM",
|
||||
"storage": "Storage",
|
||||
"connections": "Connections",
|
||||
"environments": "Environments",
|
||||
"global_title": "Global Settings",
|
||||
@@ -134,8 +145,77 @@
|
||||
"logging": "Logging Configuration",
|
||||
"logging_description": "Configure logging and task log levels.",
|
||||
"storage_description": "Configure file storage paths and patterns.",
|
||||
"synchronized_resources": "Synchronized Resources",
|
||||
"save_storage_config": "Save Storage Config",
|
||||
"save_success": "Settings saved",
|
||||
"save_failed": "Failed to save settings"
|
||||
"save_failed": "Failed to save settings",
|
||||
"load_failed": "Failed to load settings",
|
||||
"testing_connection": "Testing connection...",
|
||||
"connection_success": "Connection successful",
|
||||
"connection_failed": "Connection failed: {error}",
|
||||
"connection_failed_short": "Connection failed",
|
||||
"connection_test_failed": "Failed to test connection",
|
||||
"env_required_fields": "Please fill in all required fields (ID, Name, URL)",
|
||||
"env_updated": "Environment updated",
|
||||
"env_added": "Environment added",
|
||||
"env_deleted": "Environment deleted",
|
||||
"env_save_failed": "Failed to save environment",
|
||||
"env_delete_failed": "Failed to delete environment",
|
||||
"env_delete_confirm": "Are you sure you want to delete this environment?",
|
||||
"migration_sync": "Migration Sync",
|
||||
"migration_sync_title": "Cross-Environment ID Synchronization",
|
||||
"migration_sync_description": "Configure the background synchronization schedule and view mapped Dashboard, Chart, and Dataset IDs.",
|
||||
"migration_sync_failed": "Sync failed",
|
||||
"sync_schedule": "Sync Schedule (Cron)",
|
||||
"migration_cron_placeholder": "0 2 * * *",
|
||||
"migration_cron_hint": "Example: 0 2 * * * (daily at 2 AM UTC)",
|
||||
"saving": "Saving...",
|
||||
"syncing": "Syncing...",
|
||||
"sync_now": "Sync Now",
|
||||
"no_matching_resources": "No matching resources found.",
|
||||
"search_by_name_or_uuid": "Search by name or UUID...",
|
||||
"all_environments": "All Environments",
|
||||
"all_types": "All Types",
|
||||
"type_chart": "Chart",
|
||||
"resource_name": "Resource Name",
|
||||
"type": "Type",
|
||||
"target_id": "Target ID",
|
||||
"loading_mappings": "Loading mappings...",
|
||||
"no_synchronized_resources": "No synchronized resources found.",
|
||||
"cron_placeholder": "0 0 * * *",
|
||||
"enable_auto_backups": "Enable Automatic Backups",
|
||||
"env_url": "URL",
|
||||
"default": "Default",
|
||||
"warning": "Warning",
|
||||
"log_level": "Log Level",
|
||||
"log_file_path": "Log File Path",
|
||||
"log_file_path_placeholder": "logs/app.log",
|
||||
"max_file_size_mb": "Max File Size (MB)",
|
||||
"backup_count": "Backup Count",
|
||||
"task_log_level": "Task Log Level",
|
||||
"enable_belief_state": "Enable Belief State Logging (Beta)",
|
||||
"belief_state_hint": "Logs agent reasoning and internal state changes for debugging.",
|
||||
"save_logging": "Save Logging Config",
|
||||
"save_global_settings": "Save Global Settings",
|
||||
"no_external_connections": "No external connections configured.",
|
||||
"name": "Name",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"backup_schedule": "Backup Schedule",
|
||||
"cron_expression": "Cron Expression",
|
||||
"cron_example": "Example: 0 0 * * * (daily at midnight), */5 * * * * (every 5 minutes)",
|
||||
"env_update": "Update Environment",
|
||||
"git_config_saved": "Configuration saved",
|
||||
"git_config_deleted": "Configuration deleted",
|
||||
"git_delete_confirm": "Are you sure you want to delete this Git configuration?",
|
||||
"configured_servers": "Configured Servers",
|
||||
"add_git_server": "Add Git Server",
|
||||
"display_name": "Display Name",
|
||||
"display_name_placeholder": "e.g. My GitHub",
|
||||
"server_url": "Server URL",
|
||||
"personal_access_token": "Personal Access Token (PAT)",
|
||||
"default_repository_optional": "Default Repository (Optional)",
|
||||
"save_configuration": "Save Configuration"
|
||||
},
|
||||
"git": {
|
||||
"management": "Git Management",
|
||||
@@ -168,6 +248,9 @@
|
||||
"generate_with_ai": "Generate with AI",
|
||||
"describe_changes": "Describe your changes...",
|
||||
"changed_files": "Changed Files",
|
||||
"staged": "Staged",
|
||||
"modified_unstaged": "Modified (Unstaged)",
|
||||
"untracked": "Untracked",
|
||||
"changes_preview": "Changes Preview",
|
||||
"loading_diff": "Loading diff...",
|
||||
"no_changes": "No changes detected",
|
||||
@@ -181,7 +264,11 @@
|
||||
"push_success": "Changes pushed to remote",
|
||||
"pull_success": "Changes pulled from remote",
|
||||
"no_servers_configured": "No Git servers configured. Go to Settings -> Git to add one.",
|
||||
"remote_url_placeholder": "https://github.com/org/repo.git"
|
||||
"remote_url_placeholder": "https://github.com/org/repo.git",
|
||||
"load_branches_failed": "Failed to load branches",
|
||||
"switched_to": "Switched to {branch}",
|
||||
"created_branch": "Created branch {branch}",
|
||||
"branch_name_placeholder": "branch-name"
|
||||
},
|
||||
"dashboard": {
|
||||
"search": "Search dashboards...",
|
||||
@@ -194,6 +281,8 @@
|
||||
"next": "Next",
|
||||
"no_dashboards": "No dashboards found in this environment.",
|
||||
"select_source": "Select a source environment to view dashboards.",
|
||||
"overview": "Overview",
|
||||
"charts": "Charts",
|
||||
"validate": "Validate",
|
||||
"validation_started": "Validation started for {title}",
|
||||
"select_tool": "Select Tool",
|
||||
@@ -218,7 +307,53 @@
|
||||
"actions": "Actions",
|
||||
"action_migrate": "Migrate",
|
||||
"action_backup": "Backup",
|
||||
"action_validate": "Validate",
|
||||
"action_commit": "Commit",
|
||||
"select_all": "Select All",
|
||||
"deselect_all": "Deselect All",
|
||||
"select_visible": "Select Visible",
|
||||
"deselect_visible": "Deselect Visible",
|
||||
"selected_count": "{count} selected",
|
||||
"open_overview": "Open dashboard overview",
|
||||
"per_page_option": "{count} per page",
|
||||
"bulk_migrate": "Migrate",
|
||||
"bulk_backup": "Backup",
|
||||
"migrate_modal_title": "Migrate {count} Dashboards",
|
||||
"backup_modal_title": "Backup {count} Dashboards",
|
||||
"read_only": "(read-only)",
|
||||
"target_env_placeholder": "Select target environment...",
|
||||
"view_summary": "View Summary",
|
||||
"edit_mappings": "Edit Mappings",
|
||||
"source_database": "Source Database",
|
||||
"target_database": "Target Database",
|
||||
"match_percent": "Match %",
|
||||
"not_mapped": "Not mapped",
|
||||
"no_databases_to_map": "No databases found to map",
|
||||
"select_target_for_mappings": "Select target environment to see mappings",
|
||||
"mapping_disabled_hint": "Database mapping is disabled. Dashboards will be imported with original database references.",
|
||||
"saved": "Saved",
|
||||
"suggested": "Suggested",
|
||||
"fix_cross_filters_title": "Fix cross-filter bindings",
|
||||
"fix_cross_filters_hint": "Automatically remap chart and dataset IDs in cross-filters to target environment IDs. Recommended when migrating dashboards with cross-filters.",
|
||||
"selected_dashboards": "Selected Dashboards",
|
||||
"starting": "Starting...",
|
||||
"start_backup": "Start Backup",
|
||||
"schedule": "Schedule",
|
||||
"one_time_backup": "One-time backup",
|
||||
"schedule_backup": "Schedule backup",
|
||||
"cron_expression": "Cron expression",
|
||||
"cron_help": "Help with cron syntax",
|
||||
"cron_placeholder": "0 2 * * * (daily at 2 AM)",
|
||||
"load_failed": "Failed to load dashboards",
|
||||
"validation_start_failed": "Failed to start validation",
|
||||
"unknown_error": "Unknown error",
|
||||
"target_env_required": "Please select a target environment",
|
||||
"migration_task_failed": "Failed to create migration task",
|
||||
"backup_task_failed": "Failed to create backup task",
|
||||
"missing_context": "Missing dashboard ID or environment ID",
|
||||
"load_detail_failed": "Failed to load dashboard details",
|
||||
"no_charts": "No charts found for this dashboard.",
|
||||
"no_datasets": "No datasets found for this dashboard.",
|
||||
"view_task": "View task",
|
||||
"task_running": "Running...",
|
||||
"task_done": "Done",
|
||||
@@ -244,7 +379,14 @@
|
||||
"status_success": "Success",
|
||||
"status_failed": "Failed",
|
||||
"status_in_progress": "In progress",
|
||||
"status_partial": "Partial"
|
||||
"status_partial": "Partial",
|
||||
"id": "ID",
|
||||
"type": "Type",
|
||||
"status": "Status",
|
||||
"updated": "Updated",
|
||||
"summary": "Summary",
|
||||
"severity": "Severity",
|
||||
"message": "Message"
|
||||
},
|
||||
"datasets": {
|
||||
"empty": "No datasets found",
|
||||
@@ -264,6 +406,7 @@
|
||||
"deselect_visible": "Deselect Visible",
|
||||
"selected": "selected",
|
||||
"selected_count": "{count} selected",
|
||||
"showing": "Showing {start} to {end} of {total} datasets",
|
||||
"bulk_map_columns": "Bulk Column Mapping",
|
||||
"bulk_docs_generation": "Bulk Documentation Generation",
|
||||
"source_type": "Source Type",
|
||||
@@ -315,12 +458,63 @@
|
||||
"footer_text": "Task continues running in background",
|
||||
"drawer": "Task drawer",
|
||||
"close_drawer": "Close drawer",
|
||||
"back_to_list": "Back to task list"
|
||||
"back_to_list": "Back to task list",
|
||||
"log_stream_failed": "Failed to connect to log stream after multiple attempts.",
|
||||
"mapping_resolved": "Mapping resolved, migration continuing...",
|
||||
"mapping_resolve_failed": "Failed to resolve mapping: {error}",
|
||||
"passwords_submitted": "Passwords submitted, resuming migration...",
|
||||
"resume_failed": "Failed to resume task: {error}",
|
||||
"task_label": "Task",
|
||||
"connecting": "Connecting...",
|
||||
"live": "Live",
|
||||
"completed": "Completed",
|
||||
"awaiting_mapping": "Awaiting Mapping",
|
||||
"awaiting_input": "Awaiting Input",
|
||||
"disconnected": "Disconnected",
|
||||
"details_parameters": "Task Details & Parameters",
|
||||
"started_label": "Started",
|
||||
"plugin": "Plugin",
|
||||
"parameters": "Parameters",
|
||||
"waiting_logs": "Waiting for new logs...",
|
||||
"result_select_task": "Select a task to view result.",
|
||||
"result_not_structured": "No structured result for this task.",
|
||||
"result_llm_validation": "LLM dashboard validation",
|
||||
"result_no_summary": "No summary",
|
||||
"issues": "Issues",
|
||||
"location": "Location",
|
||||
"backup_result": "Backup result",
|
||||
"total": "Total",
|
||||
"successful": "Successful",
|
||||
"failed": "Failed",
|
||||
"errors": "Errors",
|
||||
"migration_result": "Migration result",
|
||||
"selected": "Selected",
|
||||
"with_errors": "With errors",
|
||||
"migration_errors": "Migration errors",
|
||||
"clear_confirm": "Are you sure you want to clear tasks?",
|
||||
"fetch_task_details_failed": "Failed to fetch full task details:",
|
||||
"clear_tasks": "Clear Tasks",
|
||||
"clear_non_running": "Clear All Non-Running",
|
||||
"clear_failed": "Clear Failed",
|
||||
"clear_awaiting_input": "Clear Awaiting Input",
|
||||
"keys": "keys",
|
||||
"mappings": "Mappings"
|
||||
},
|
||||
"auth": {
|
||||
"login": "Login",
|
||||
"logging_in": "Logging in...",
|
||||
"or_continue_with": "Or continue with",
|
||||
"corporate_sso": "Corporate SSO (ADFS)",
|
||||
"enter_credentials": "Please enter both username and password",
|
||||
"invalid_credentials": "Invalid username or password",
|
||||
"login_error": "An error occurred during login",
|
||||
"profile_fetch_failed": "Failed to fetch user profile: {error}"
|
||||
},
|
||||
"migration": {
|
||||
"source_env": "Source Environment",
|
||||
"target_env": "Target Environment",
|
||||
"loading_envs": "Loading environments...",
|
||||
"loading_envs_failed": "Failed to load environments",
|
||||
"select_both_envs": "Please select both source and target environments.",
|
||||
"different_envs": "Source and target environments must be different.",
|
||||
"select_dashboards": "Please select at least one dashboard to migrate.",
|
||||
@@ -343,9 +537,25 @@
|
||||
"close": "Close assistant",
|
||||
"send": "Send",
|
||||
"input_placeholder": "Type a command...",
|
||||
"conversation": "Conversation",
|
||||
"conversations": "Conversations",
|
||||
"new": "New",
|
||||
"active": "Active",
|
||||
"archived": "Archived",
|
||||
"more": "More",
|
||||
"loading_history": "Loading history...",
|
||||
"loading_older": "Loading older messages...",
|
||||
"try_commands": "Try commands:",
|
||||
"sample_command_branch": "create branch feature/new-dashboard for dashboard 42",
|
||||
"sample_command_migration": "run migration from dev to prod for dashboard 42",
|
||||
"sample_command_status": "check task status task-123",
|
||||
"you": "You",
|
||||
"assistant": "Assistant",
|
||||
"task_id": "task_id",
|
||||
"open_task_drawer": "Open Task Drawer",
|
||||
"thinking": "Thinking",
|
||||
"request_failed": "Assistant request failed",
|
||||
"action_failed": "Action failed",
|
||||
"states": {
|
||||
"started": "Started",
|
||||
"success": "Success",
|
||||
@@ -474,7 +684,10 @@
|
||||
"password": "Password",
|
||||
"password_hint": "Leave blank to keep current password.",
|
||||
"roles_hint": "Hold Ctrl/Cmd to select multiple roles.",
|
||||
"confirm_delete": "Are you sure you want to delete user {username}?"
|
||||
"confirm_delete": "Are you sure you want to delete user {username}?",
|
||||
"load_failed": "Failed to load admin data.",
|
||||
"save_failed": "Failed to save user: {error}",
|
||||
"delete_failed": "Failed to delete user: {error}"
|
||||
},
|
||||
"roles": {
|
||||
"title": "Role Management",
|
||||
@@ -487,7 +700,10 @@
|
||||
"modal_create_title": "Create New Role",
|
||||
"modal_edit_title": "Edit Role",
|
||||
"permissions_hint": "Select permissions for this role.",
|
||||
"confirm_delete": "Are you sure you want to delete role {name}?"
|
||||
"confirm_delete": "Are you sure you want to delete role {name}?",
|
||||
"load_failed": "Failed to load roles data.",
|
||||
"save_failed": "Failed to save role: {error}",
|
||||
"delete_failed": "Failed to delete role: {error}"
|
||||
},
|
||||
"settings": {
|
||||
"title": "ADFS Configuration",
|
||||
@@ -499,7 +715,19 @@
|
||||
"ad_group_dn": "AD Group Distinguished Name",
|
||||
"ad_group_hint": "The full DN of the Active Directory group.",
|
||||
"local_role_select": "Local System Role",
|
||||
"select_role": "Select a role"
|
||||
"select_role": "Select a role",
|
||||
"load_failed": "Failed to load roles or configuration.",
|
||||
"fill_all_fields": "Please fill in all fields.",
|
||||
"create_mapping_failed": "Failed to create mapping: {error}",
|
||||
"save_logging_failed": "Failed to save logging configuration: {error}",
|
||||
"loading_logging": "Loading logging configuration...",
|
||||
"app_log_level": "Application Log Level",
|
||||
"app_log_level_hint": "Controls the verbosity of application logs.",
|
||||
"task_log_level_hint": "Minimum level for logs stored in task history. DEBUG shows all logs.",
|
||||
"belief_state_hint": "When disabled, belief scope logs are hidden. Requires DEBUG level to see in task logs.",
|
||||
"save_configuration": "Save Configuration",
|
||||
"saved": "Saved",
|
||||
"ad_group_placeholder": "e.g. CN=SS_ADMINS,OU=Groups,DC=org"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,18 @@
|
||||
"activity": "Активность",
|
||||
"user_menu": "Меню пользователя",
|
||||
"user": "Пользователь",
|
||||
"brand": "Superset Tools",
|
||||
"unknown": "Неизвестно",
|
||||
"yes": "Да",
|
||||
"no": "Нет",
|
||||
"not_available": "Н/Д",
|
||||
"first": "Первая",
|
||||
"last": "Последняя",
|
||||
"on": "Вкл",
|
||||
"off": "Выкл",
|
||||
"per_page": "на страницу",
|
||||
"close_modal": "Закрыть модальное окно"
|
||||
"close_modal": "Закрыть модальное окно",
|
||||
"choose_environment": "-- Выберите окружение --"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Главная",
|
||||
@@ -88,12 +94,15 @@
|
||||
"dataset_desc": "Описание датасета",
|
||||
"column_doc": "Документация колонок",
|
||||
"apply_doc": "Применить документацию",
|
||||
"applying": "Применение..."
|
||||
"applying": "Применение...",
|
||||
"validation_report_title": "Отчет валидации",
|
||||
"no_validation_result": "Результат валидации недоступен."
|
||||
},
|
||||
"settings": {
|
||||
"title": "Настройки",
|
||||
"language": "Язык",
|
||||
"appearance": "Внешний вид",
|
||||
"llm": "LLM",
|
||||
"connections": "Подключения",
|
||||
"environments": "Окружения",
|
||||
"global_title": "Общие настройки",
|
||||
@@ -134,8 +143,78 @@
|
||||
"logging": "Настройка логирования",
|
||||
"logging_description": "Настройка уровней логирования задач.",
|
||||
"storage_description": "Настройка путей и шаблонов файлового хранилища.",
|
||||
"storage": "Хранилище",
|
||||
"synchronized_resources": "Синхронизированные ресурсы",
|
||||
"save_storage_config": "Сохранить настройки хранилища",
|
||||
"save_success": "Настройки сохранены",
|
||||
"save_failed": "Ошибка сохранения настроек"
|
||||
"save_failed": "Ошибка сохранения настроек",
|
||||
"load_failed": "Не удалось загрузить настройки",
|
||||
"testing_connection": "Проверка подключения...",
|
||||
"connection_success": "Подключение успешно",
|
||||
"connection_failed": "Ошибка подключения: {error}",
|
||||
"connection_failed_short": "Ошибка подключения",
|
||||
"connection_test_failed": "Не удалось проверить подключение",
|
||||
"env_required_fields": "Заполните обязательные поля (ID, Name, URL)",
|
||||
"env_updated": "Окружение обновлено",
|
||||
"env_added": "Окружение добавлено",
|
||||
"env_deleted": "Окружение удалено",
|
||||
"env_save_failed": "Не удалось сохранить окружение",
|
||||
"env_delete_failed": "Не удалось удалить окружение",
|
||||
"env_delete_confirm": "Вы уверены, что хотите удалить это окружение?",
|
||||
"migration_sync": "Синхронизация миграции",
|
||||
"migration_sync_title": "Синхронизация ID между окружениями",
|
||||
"migration_sync_description": "Настройте расписание фоновой синхронизации и просматривайте сопоставленные ID дашбордов, чартов и датасетов.",
|
||||
"migration_sync_failed": "Синхронизация не удалась",
|
||||
"sync_schedule": "Расписание синхронизации (Cron)",
|
||||
"migration_cron_placeholder": "0 2 * * *",
|
||||
"migration_cron_hint": "Пример: 0 2 * * * (ежедневно в 02:00 UTC)",
|
||||
"saving": "Сохранение...",
|
||||
"syncing": "Синхронизация...",
|
||||
"sync_now": "Синхронизировать сейчас",
|
||||
"no_matching_resources": "Подходящие ресурсы не найдены.",
|
||||
"search_by_name_or_uuid": "Поиск по имени или UUID...",
|
||||
"all_environments": "Все окружения",
|
||||
"all_types": "Все типы",
|
||||
"type_chart": "Чарт",
|
||||
"resource_name": "Имя ресурса",
|
||||
"type": "Тип",
|
||||
"target_id": "Целевой ID",
|
||||
"loading_mappings": "Загрузка маппингов...",
|
||||
"no_synchronized_resources": "Синхронизированные ресурсы не найдены.",
|
||||
"cron_placeholder": "0 0 * * *",
|
||||
"enable_auto_backups": "Включить автоматические бэкапы",
|
||||
"env_url": "URL",
|
||||
"default": "По умолчанию",
|
||||
"warning": "Внимание",
|
||||
"log_level": "Уровень логирования",
|
||||
"log_file_path": "Путь к файлу логов",
|
||||
"log_file_path_placeholder": "logs/app.log",
|
||||
"max_file_size_mb": "Максимальный размер файла (МБ)",
|
||||
"backup_count": "Количество ротаций",
|
||||
"task_log_level": "Уровень логов задач",
|
||||
"enable_belief_state": "Включить логирование Belief State (Beta)",
|
||||
"belief_state_hint": "Логирует рассуждения агента и изменения внутреннего состояния для отладки.",
|
||||
"save_logging": "Сохранить настройки логирования",
|
||||
"save_global_settings": "Сохранить общие настройки",
|
||||
"no_external_connections": "Внешние подключения не настроены.",
|
||||
"name": "Название",
|
||||
"username": "Имя пользователя",
|
||||
"password": "Пароль",
|
||||
"backup_schedule": "Расписание бэкапа",
|
||||
"cron_expression": "Cron-выражение",
|
||||
"cron_example": "Пример: 0 0 * * * (ежедневно в полночь), */5 * * * * (каждые 5 минут)",
|
||||
"env_update": "Обновить окружение",
|
||||
"git_config_saved": "Конфигурация сохранена",
|
||||
"git_config_deleted": "Конфигурация удалена",
|
||||
"git_delete_confirm": "Вы уверены, что хотите удалить эту Git-конфигурацию?",
|
||||
"configured_servers": "Настроенные серверы",
|
||||
"add_git_server": "Добавить Git-сервер",
|
||||
"display_name": "Отображаемое имя",
|
||||
"display_name_placeholder": "например, My GitHub",
|
||||
"server_url": "URL сервера",
|
||||
"personal_access_token": "Персональный токен доступа (PAT)",
|
||||
"default_repository_optional": "Репозиторий по умолчанию (опционально)",
|
||||
"save_configuration": "Сохранить конфигурацию"
|
||||
},
|
||||
"git": {
|
||||
"management": "Управление Git",
|
||||
@@ -168,6 +247,9 @@
|
||||
"generate_with_ai": "Сгенерировать с AI",
|
||||
"describe_changes": "Опишите ваши изменения...",
|
||||
"changed_files": "Измененные файлы",
|
||||
"staged": "Подготовлено",
|
||||
"modified_unstaged": "Изменено (не подготовлено)",
|
||||
"untracked": "Новый файл",
|
||||
"changes_preview": "Предпросмотр изменений",
|
||||
"loading_diff": "Загрузка diff...",
|
||||
"no_changes": "Изменения не обнаружены",
|
||||
@@ -181,7 +263,11 @@
|
||||
"push_success": "Изменения отправлены в remote",
|
||||
"pull_success": "Изменения получены из remote",
|
||||
"no_servers_configured": "Git-серверы не настроены. Перейдите в Настройки -> Git для добавления.",
|
||||
"remote_url_placeholder": "https://github.com/org/repo.git"
|
||||
"remote_url_placeholder": "https://github.com/org/repo.git",
|
||||
"load_branches_failed": "Не удалось загрузить ветки",
|
||||
"switched_to": "Переключено на {branch}",
|
||||
"created_branch": "Создана ветка {branch}",
|
||||
"branch_name_placeholder": "имя-ветки"
|
||||
},
|
||||
"dashboard": {
|
||||
"search": "Поиск дашбордов...",
|
||||
@@ -194,6 +280,8 @@
|
||||
"next": "Вперед",
|
||||
"no_dashboards": "Дашборды не найдены в этом окружении.",
|
||||
"select_source": "Выберите исходное окружение для просмотра дашбордов.",
|
||||
"overview": "Обзор",
|
||||
"charts": "Чарты",
|
||||
"validate": "Проверить",
|
||||
"validation_started": "Проверка запущена для {title}",
|
||||
"select_tool": "Выберите инструмент",
|
||||
@@ -217,7 +305,53 @@
|
||||
"actions": "Действия",
|
||||
"action_migrate": "Мигрировать",
|
||||
"action_backup": "Создать бэкап",
|
||||
"action_validate": "Проверить",
|
||||
"action_commit": "Зафиксировать",
|
||||
"select_all": "Выбрать все",
|
||||
"deselect_all": "Снять выбор со всех",
|
||||
"select_visible": "Выбрать видимые",
|
||||
"deselect_visible": "Снять выбор с видимых",
|
||||
"selected_count": "{count} выбрано",
|
||||
"open_overview": "Открыть обзор дашборда",
|
||||
"per_page_option": "{count} на страницу",
|
||||
"bulk_migrate": "Мигрировать",
|
||||
"bulk_backup": "Создать бэкап",
|
||||
"migrate_modal_title": "Миграция {count} дашбордов",
|
||||
"backup_modal_title": "Бэкап {count} дашбордов",
|
||||
"read_only": "(только чтение)",
|
||||
"target_env_placeholder": "Выберите целевое окружение...",
|
||||
"view_summary": "Показать сводку",
|
||||
"edit_mappings": "Редактировать маппинги",
|
||||
"source_database": "Исходная БД",
|
||||
"target_database": "Целевая БД",
|
||||
"match_percent": "Совпадение %",
|
||||
"not_mapped": "Не сопоставлено",
|
||||
"no_databases_to_map": "Нет баз данных для маппинга",
|
||||
"select_target_for_mappings": "Выберите целевое окружение, чтобы увидеть маппинги",
|
||||
"mapping_disabled_hint": "Маппинг БД отключен. Дашборды будут импортированы с исходными ссылками на базы данных.",
|
||||
"saved": "Сохранено",
|
||||
"suggested": "Рекомендовано",
|
||||
"fix_cross_filters_title": "Исправить связи кросс-фильтрации",
|
||||
"fix_cross_filters_hint": "Автоматически перепривязать ID чартов и датасетов в кросс-фильтрах к ID целевого окружения. Рекомендуется при миграции дашбордов с кросс-фильтрами.",
|
||||
"selected_dashboards": "Выбранные дашборды",
|
||||
"starting": "Запуск...",
|
||||
"start_backup": "Запустить бэкап",
|
||||
"schedule": "Расписание",
|
||||
"one_time_backup": "Разовый бэкап",
|
||||
"schedule_backup": "Бэкап по расписанию",
|
||||
"cron_expression": "Cron-выражение",
|
||||
"cron_help": "Помощь по синтаксису cron",
|
||||
"cron_placeholder": "0 2 * * * (ежедневно в 02:00)",
|
||||
"load_failed": "Не удалось загрузить дашборды",
|
||||
"validation_start_failed": "Не удалось запустить проверку",
|
||||
"unknown_error": "Неизвестная ошибка",
|
||||
"target_env_required": "Пожалуйста, выберите целевое окружение",
|
||||
"migration_task_failed": "Не удалось создать задачу миграции",
|
||||
"backup_task_failed": "Не удалось создать задачу бэкапа",
|
||||
"missing_context": "Отсутствует ID дашборда или окружения",
|
||||
"load_detail_failed": "Не удалось загрузить детали дашборда",
|
||||
"no_charts": "Для этого дашборда чарты не найдены.",
|
||||
"no_datasets": "Для этого дашборда датасеты не найдены.",
|
||||
"view_task": "Просмотреть задачу",
|
||||
"task_running": "Выполняется...",
|
||||
"task_done": "Готово",
|
||||
@@ -243,7 +377,14 @@
|
||||
"status_success": "Успешно",
|
||||
"status_failed": "Ошибка",
|
||||
"status_in_progress": "В процессе",
|
||||
"status_partial": "Частично"
|
||||
"status_partial": "Частично",
|
||||
"id": "ID",
|
||||
"type": "Тип",
|
||||
"status": "Статус",
|
||||
"updated": "Обновлено",
|
||||
"summary": "Сводка",
|
||||
"severity": "Серьезность",
|
||||
"message": "Сообщение"
|
||||
},
|
||||
"datasets": {
|
||||
"empty": "Датасеты не найдены",
|
||||
@@ -263,6 +404,7 @@
|
||||
"deselect_visible": "Снять выбор с видимых",
|
||||
"selected": "выбрано",
|
||||
"selected_count": "Выбрано: {count}",
|
||||
"showing": "Показано с {start} по {end} из {total} датасетов",
|
||||
"bulk_map_columns": "Массовый маппинг колонок",
|
||||
"bulk_docs_generation": "Массовая генерация документации",
|
||||
"source_type": "Тип источника",
|
||||
@@ -314,12 +456,63 @@
|
||||
"footer_text": "Задача продолжает работать в фоновом режиме",
|
||||
"drawer": "Панель задач",
|
||||
"close_drawer": "Закрыть панель задач",
|
||||
"back_to_list": "Назад к списку задач"
|
||||
"back_to_list": "Назад к списку задач",
|
||||
"log_stream_failed": "Не удалось подключиться к потоку логов после нескольких попыток.",
|
||||
"mapping_resolved": "Маппинг сохранен, миграция продолжается...",
|
||||
"mapping_resolve_failed": "Не удалось сохранить маппинг: {error}",
|
||||
"passwords_submitted": "Пароли отправлены, миграция возобновляется...",
|
||||
"resume_failed": "Не удалось возобновить задачу: {error}",
|
||||
"task_label": "Задача",
|
||||
"connecting": "Подключение...",
|
||||
"live": "Онлайн",
|
||||
"completed": "Завершено",
|
||||
"awaiting_mapping": "Ожидание маппинга",
|
||||
"awaiting_input": "Ожидание ввода",
|
||||
"disconnected": "Отключено",
|
||||
"details_parameters": "Детали задачи и параметры",
|
||||
"started_label": "Запущено",
|
||||
"plugin": "Плагин",
|
||||
"parameters": "Параметры",
|
||||
"waiting_logs": "Ожидание новых логов...",
|
||||
"result_select_task": "Выберите задачу, чтобы увидеть результат.",
|
||||
"result_not_structured": "Для этой задачи нет структурированного результата.",
|
||||
"result_llm_validation": "LLM проверка дашборда",
|
||||
"result_no_summary": "Нет summary",
|
||||
"issues": "Проблемы",
|
||||
"location": "Локация",
|
||||
"backup_result": "Результат бэкапа",
|
||||
"total": "Всего",
|
||||
"successful": "Успешно",
|
||||
"failed": "С ошибками",
|
||||
"errors": "Ошибки",
|
||||
"migration_result": "Результат миграции",
|
||||
"selected": "Выбрано",
|
||||
"with_errors": "С ошибками",
|
||||
"migration_errors": "Ошибки миграции",
|
||||
"clear_confirm": "Вы уверены, что хотите очистить задачи?",
|
||||
"fetch_task_details_failed": "Не удалось получить полные детали задачи:",
|
||||
"clear_tasks": "Очистить задачи",
|
||||
"clear_non_running": "Очистить все неактивные",
|
||||
"clear_failed": "Очистить ошибки",
|
||||
"clear_awaiting_input": "Очистить ожидающие ввода",
|
||||
"keys": "ключей",
|
||||
"mappings": "Маппинги"
|
||||
},
|
||||
"auth": {
|
||||
"login": "Вход",
|
||||
"logging_in": "Вход...",
|
||||
"or_continue_with": "Или продолжить через",
|
||||
"corporate_sso": "Корпоративный SSO (ADFS)",
|
||||
"enter_credentials": "Введите username и password",
|
||||
"invalid_credentials": "Неверный username или password",
|
||||
"login_error": "Произошла ошибка при входе",
|
||||
"profile_fetch_failed": "Не удалось получить профиль пользователя: {error}"
|
||||
},
|
||||
"migration": {
|
||||
"source_env": "Исходное окружение",
|
||||
"target_env": "Целевое окружение",
|
||||
"loading_envs": "Загрузка окружений...",
|
||||
"loading_envs_failed": "Не удалось загрузить окружения",
|
||||
"select_both_envs": "Выберите исходное и целевое окружение.",
|
||||
"different_envs": "Исходное и целевое окружения должны отличаться.",
|
||||
"select_dashboards": "Выберите хотя бы один дашборд для миграции.",
|
||||
@@ -342,9 +535,25 @@
|
||||
"close": "Закрыть ассистента",
|
||||
"send": "Отправить",
|
||||
"input_placeholder": "Введите команду...",
|
||||
"conversation": "Диалог",
|
||||
"conversations": "Диалоги",
|
||||
"new": "Новый",
|
||||
"active": "Активные",
|
||||
"archived": "Архив",
|
||||
"more": "Еще",
|
||||
"loading_history": "Загрузка истории...",
|
||||
"loading_older": "Загрузка более ранних сообщений...",
|
||||
"try_commands": "Попробуйте команды:",
|
||||
"sample_command_branch": "создай ветку feature/new-dashboard для дашборда 42",
|
||||
"sample_command_migration": "запусти миграцию с dev на prod для дашборда 42",
|
||||
"sample_command_status": "проверь статус задачи task-123",
|
||||
"you": "Вы",
|
||||
"assistant": "Ассистент",
|
||||
"task_id": "task_id",
|
||||
"open_task_drawer": "Открыть Task Drawer",
|
||||
"thinking": "Думаю",
|
||||
"request_failed": "Ошибка запроса к ассистенту",
|
||||
"action_failed": "Не удалось выполнить действие",
|
||||
"states": {
|
||||
"started": "Запущено",
|
||||
"success": "Успешно",
|
||||
@@ -473,7 +682,10 @@
|
||||
"password": "Пароль",
|
||||
"password_hint": "Оставьте пустым, чтобы не менять пароль.",
|
||||
"roles_hint": "Удерживайте Ctrl/Cmd для выбора нескольких ролей.",
|
||||
"confirm_delete": "Вы уверены, что хотите удалить пользователя {username}?"
|
||||
"confirm_delete": "Вы уверены, что хотите удалить пользователя {username}?",
|
||||
"load_failed": "Не удалось загрузить данные админки.",
|
||||
"save_failed": "Не удалось сохранить пользователя: {error}",
|
||||
"delete_failed": "Не удалось удалить пользователя: {error}"
|
||||
},
|
||||
"roles": {
|
||||
"title": "Управление ролями",
|
||||
@@ -486,7 +698,10 @@
|
||||
"modal_create_title": "Создать новую роль",
|
||||
"modal_edit_title": "Редактировать роль",
|
||||
"permissions_hint": "Выберите права для этой роли.",
|
||||
"confirm_delete": "Вы уверены, что хотите удалить роль {name}?"
|
||||
"confirm_delete": "Вы уверены, что хотите удалить роль {name}?",
|
||||
"load_failed": "Не удалось загрузить данные ролей.",
|
||||
"save_failed": "Не удалось сохранить роль: {error}",
|
||||
"delete_failed": "Не удалось удалить роль: {error}"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Настройка ADFS",
|
||||
@@ -498,7 +713,19 @@
|
||||
"ad_group_dn": "Distinguished Name группы AD",
|
||||
"ad_group_hint": "Полный DN группы Active Directory.",
|
||||
"local_role_select": "Локальная системная роль",
|
||||
"select_role": "Выберите роль"
|
||||
"select_role": "Выберите роль",
|
||||
"load_failed": "Не удалось загрузить роли или конфигурацию.",
|
||||
"fill_all_fields": "Пожалуйста, заполните все поля.",
|
||||
"create_mapping_failed": "Не удалось создать маппинг: {error}",
|
||||
"save_logging_failed": "Не удалось сохранить настройки логирования: {error}",
|
||||
"loading_logging": "Загрузка конфигурации логирования...",
|
||||
"app_log_level": "Уровень логов приложения",
|
||||
"app_log_level_hint": "Определяет детализацию логов приложения.",
|
||||
"task_log_level_hint": "Минимальный уровень логов, сохраняемых в истории задач. DEBUG показывает все логи.",
|
||||
"belief_state_hint": "При выключении логи belief scope скрываются. Для отображения в логах задач требуется DEBUG.",
|
||||
"save_configuration": "Сохранить конфигурацию",
|
||||
"saved": "Сохранено",
|
||||
"ad_group_placeholder": "например, CN=SS_ADMINS,OU=Groups,DC=org"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user