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

@@ -14,6 +14,8 @@
import Button from "#lib/components/ui/Button.svelte";
import Icon from "#lib/components/ui/Icon.svelte";
import QrCode from "#lib/components/ui/QrCode.svelte";
import { t } from "#lib/i18n/locale.svelte.js";
import type { MessageKey } from "#lib/i18n/messages.js";
import { accounts } from "#lib/stores/accounts.svelte.js";
import { toasts } from "#lib/stores/toasts.svelte.js";
@@ -30,12 +32,9 @@
let busy = $state(false);
let attempt = 0;
const hints: Record<Step, string> = {
code: "Код отправлен в Telegram на этот номер.",
password: "Аккаунт защищён двухэтапной аутентификацией.",
phone: "Номер телефона в международном формате, например +79991234567.",
qr: "Telegram → Настройки → Устройства → Подключить устройство, и наведите камеру на код.",
};
function hint(current: Step): string {
return t(`login.hint.${current}`);
}
const filled = $derived.by(() => {
if (step === "phone") {
@@ -58,12 +57,12 @@
if (state.account) {
accounts.select(state.account.account_id);
}
toasts.success("Аккаунт добавлен");
toasts.success(t("login.added"));
open = false;
}
function fail(error: unknown, fallback: string) {
toasts.error(error instanceof ApiError ? error.detail : fallback);
function fail(error: unknown, fallback: MessageKey) {
toasts.error(error instanceof ApiError ? error.detail : t(fallback));
}
function drop() {
@@ -89,7 +88,7 @@
}
} catch (error) {
if (mine === attempt) {
fail(error, "Не удалось получить QR-код");
fail(error, "login.qrFailed");
}
}
}
@@ -135,7 +134,7 @@
try {
await apply(await next());
} catch (error) {
fail(error, "Не удалось войти");
fail(error, "login.failed");
} finally {
busy = false;
}
@@ -159,29 +158,29 @@
<Dialog.Overlay class="dialog-overlay" />
<Dialog.Content class="dialog-content">
<header class="dialog-head">
<Dialog.Title class="dialog-title">Добавить аккаунт</Dialog.Title>
<Dialog.Close aria-label="Закрыть" class="dialog-close">
<Dialog.Title class="dialog-title">{t("login.title")}</Dialog.Title>
<Dialog.Close aria-label={t("common.close")} class="dialog-close">
<Icon name="close" size="1.25rem" />
</Dialog.Close>
</header>
{#if step === "qr"}
<div class="dialog-body">
<p class="hint">{hints.qr}</p>
<p class="hint">{hint("qr")}</p>
<div class="qr-slot">
{#if qrUrl}
<QrCode label="QR-код для входа в Telegram" value={qrUrl} />
<QrCode label={t("login.qrLabel")} value={qrUrl} />
{/if}
</div>
</div>
<div class="dialog-actions">
<Button onclick={usePhone} pill variant="text">
Войти по номеру телефона
{t("login.byPhone")}
</Button>
</div>
{:else}
<form onsubmit={submit}>
<div class="dialog-body">
<p class="hint">{hints[step]}</p>
<p class="hint">{hint(step)}</p>
{#if step === "phone"}
<div class="input-group">
<input
@@ -192,7 +191,7 @@
type="tel"
bind:value={phone}
>
<label for="login-phone">Номер телефона</label>
<label for="login-phone">{t("login.phone")}</label>
</div>
{:else if step === "code"}
<div class="input-group">
@@ -205,7 +204,7 @@
type="text"
bind:value={code}
>
<label for="login-code">Код подтверждения</label>
<label for="login-code">{t("login.code")}</label>
</div>
{:else}
<div class="input-group">
@@ -213,17 +212,19 @@
autocomplete="current-password"
class="form-control"
id="login-password"
placeholder="Пароль"
placeholder={t("login.passwordPlaceholder")}
type="password"
bind:value={password}
>
<label for="login-password">Облачный пароль</label>
<label for="login-password">{t("login.password")}</label>
</div>
{/if}
</div>
<div class="dialog-actions">
{#if step === "phone"}
<Button onclick={useQr} pill variant="text">QR-код</Button>
<Button onclick={useQr} pill variant="text">
{t("login.qr")}
</Button>
{/if}
<Button
disabled={busy || !filled}
@@ -231,7 +232,7 @@
pill
type="submit"
>
{step === "phone" ? "Отправить код" : "Продолжить"}
{step === "phone" ? t("login.sendCode") : t("login.continue")}
</Button>
</div>
</form>