feat(frontend): storage, trash, policy, stories, shares, jobs, bots, media, login and notes speak russian and english

This commit is contained in:
hh committed 2026-10-19 03:53:08 +00:00
1 parent e5a5edcaae
commit 4a5c92f0e9
51 files changed
+1504 -588

No files matched your search

+21 -18
View File
@@ -15,6 +15,7 @@
import Icon from "#lib/components/ui/Icon.svelte";
import Spinner from "#lib/components/ui/Spinner.svelte";
import { formatBytes, mediaKindLabel } from "#lib/format/media.js";
import { t } from "#lib/i18n/locale.svelte.js";
import { poster } from "#lib/media/poster.js";
import { shareUi } from "#lib/stores/shares.svelte.js";
import { toasts } from "#lib/stores/toasts.svelte.js";
@@ -61,7 +62,9 @@
const canSave = $derived(
currentMediaId !== null && (fileOnly || result?.state === "ready")
);
const title = $derived(fileName ?? mediaKindLabel(kind) ?? "Медиа");
const title = $derived(
fileName ?? mediaKindLabel(kind) ?? t("media.kind.other")
);
const caption = $derived(items[index]?.caption);
function revoke() {
@@ -124,7 +127,7 @@
}
} catch {
if (current === token) {
toasts.error("Failed to load media");
toasts.error(t("media.loadFailed"));
}
} finally {
if (current === token) {
@@ -139,9 +142,9 @@
}
try {
await fetchMedia(chatId, messageId);
toasts.success("Скачивание поставлено в очередь");
toasts.success(t("media.queued"));
} catch {
toasts.error("Не удалось поставить в очередь");
toasts.error(t("media.queueFailed"));
}
}
@@ -153,7 +156,7 @@
try {
await downloadMedia(currentMediaId);
} catch {
toasts.error("Не удалось скачать файл");
toasts.error(t("ui.downloadFailed"));
} finally {
saving = false;
}
@@ -225,7 +228,7 @@
{#if canSave}
{#if ontrash}
<button
aria-label="В корзину"
aria-label={t("storage.toTrash")}
class="media-action"
onclick={trash}
type="button"
@@ -239,7 +242,7 @@
})}
<button
{...props}
aria-label="Скачать файл"
aria-label={t("ui.downloadFile")}
class="media-action"
onclick={save}
type="button"
@@ -249,15 +252,15 @@
{/snippet}
{#snippet menu()}
<ContextMenuItem icon="download" onselect={save}>
Скачать файл
{t("ui.downloadFile")}
</ContextMenuItem>
<ContextMenuItem icon="allow-share" onselect={share}>
Доступ по ссылке
{t("ui.shareLink")}
</ContextMenuItem>
{/snippet}
</ContextMenu>
<button
aria-label="Доступ по ссылке"
aria-label={t("ui.shareLink")}
class="media-action"
onclick={share}
type="button"
@@ -265,7 +268,7 @@
<Icon name="allow-share" size="1.375rem" />
</button>
{/if}
<Dialog.Close aria-label="Закрыть" class="media-close">
<Dialog.Close aria-label={t("common.close")} class="media-close">
<Icon name="close" size="1.5rem" />
</Dialog.Close>
</div>
@@ -276,7 +279,7 @@
{#if loading}
<Spinner color="white" />
{:else if result?.state === "ready" && isImage}
<img alt={kind} class="media-image" src={result.url}>
<img alt={title} class="media-image" src={result.url}>
{:else if result?.state === "ready" && isVideo}
<!-- svelte-ignore a11y_media_has_caption -->
<!-- biome-ignore lint/a11y/useMediaCaption: archived media has no captions -->
@@ -301,24 +304,24 @@
{#if currentMediaId !== null}
<button class="media-download" onclick={save} type="button">
<Icon name="download" />
Скачать файл
{t("ui.downloadFile")}
</button>
{/if}
</div>
{:else if result?.state === "not-downloaded"}
<div class="media-message">
<p>Файл ещё не скачан в архив.</p>
<p>{t("media.notDownloaded")}</p>
<Button fluid onclick={queueFetch} variant="primary">
Скачать в архив
{t("media.downloadToArchive")}
</Button>
</div>
{:else if result?.state === "missing"}
<p class="media-message">Файл не найден.</p>
<p class="media-message">{t("media.missing")}</p>
{/if}
</div>
{#if hasNav}
<button
aria-label="Previous"
aria-label={t("ui.previous")}
class="media-nav prev"
disabled={index === 0}
onclick={() => step(-1)}
@@ -327,7 +330,7 @@
<Icon name="previous" size="1.75rem" />
</button>
<button
aria-label="Next"
aria-label={t("ui.next")}
class="media-nav next"
disabled={index === items.length - 1}
onclick={() => step(1)}