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

+54 -53
View File
@@ -1,20 +1,9 @@
import type { CaptureToggles, PolicyScopeType } from "#lib/api/types.js";
import { plural } from "#lib/format/shares.js";
import { t } from "#lib/i18n/locale.svelte.js";
export type ToggleKey = keyof CaptureToggles;
export const TOGGLE_LABELS: Record<ToggleKey, string> = {
backfill: "Бэкфилл",
media: "Медиа",
messages: "Сообщения",
presence: "Присутствие",
profile_history: "История профиля",
reactions: "Реакции",
self_destruct_media: "Исчезающие",
stories: "Сторис",
stt: "Расшифровка",
track_edits_deletes: "Правки, удаления",
};
type DefaultScope = "channel" | "dm" | "group";
export const TOGGLE_KEYS: ToggleKey[] = [
"messages",
@@ -29,16 +18,10 @@ export const TOGGLE_KEYS: ToggleKey[] = [
"backfill",
];
export const DEFAULT_LABELS: Partial<Record<PolicyScopeType, string>> = {
default_channel: "Каналы",
default_dm: "Личные чаты",
default_group: "Группы",
};
const PARENT_LABELS: Partial<Record<PolicyScopeType, string>> = {
default_channel: "у каналов",
default_dm: "у личных чатов",
default_group: "у групп",
const DEFAULT_SCOPES: Partial<Record<PolicyScopeType, DefaultScope>> = {
default_channel: "channel",
default_dm: "dm",
default_group: "group",
};
const SHOWN_CHIPS = 3;
@@ -50,6 +33,19 @@ export interface Chip {
sign: "plus" | "minus";
}
export function toggleLabel(key: ToggleKey): string {
return t(`policy.toggle.${key}`);
}
function exceptLabel(key: ToggleKey): string {
return t(`policy.except.${key}`);
}
export function defaultLabel(scopeType: PolicyScopeType): string {
const scope = DEFAULT_SCOPES[scopeType];
return scope ? t(`policy.default.${scope}`) : "";
}
export function pickToggles(source: CaptureToggles): CaptureToggles {
return {
backfill: source.backfill,
@@ -77,37 +73,31 @@ export function sameToggles(a: CaptureToggles, b: CaptureToggles): boolean {
return TOGGLE_KEYS.every((key) => a[key] === b[key]);
}
const EXCEPT_LABELS: Record<ToggleKey, string> = {
backfill: "бэкфилла",
media: "медиа",
messages: "сообщений",
presence: "присутствия",
profile_history: "истории профиля",
reactions: "реакций",
self_destruct_media: "исчезающих",
stories: "сторис",
stt: "расшифровки",
track_edits_deletes: "правок и удалений",
};
function exceptList(keys: ToggleKey[]): string {
const [first, second] = keys.map(exceptLabel);
return second === undefined
? (first ?? "")
: t("policy.summary.pair", { a: first ?? "", b: second });
}
export function summary(toggles: CaptureToggles): string {
const on = TOGGLE_KEYS.filter((key) => toggles[key]);
const off = TOGGLE_KEYS.filter((key) => !toggles[key]);
if (off.length === 0) {
return "Всё";
return t("policy.summary.all");
}
if (on.length === 0) {
return "Ничего";
return t("policy.summary.none");
}
if (on.length === 1 && on[0] === "messages") {
return "Только сообщения";
return t("policy.summary.messagesOnly");
}
if (off.length <= SHORT_LIST) {
return `Всё, кроме ${off.map((key) => EXCEPT_LABELS[key]).join(" и ")}`;
return t("policy.summary.except", { list: exceptList(off) });
}
const names = on.slice(0, SHORT_LIST).map((key) => TOGGLE_LABELS[key]);
const rest = on.length - names.length;
return rest > 0 ? `${names.join(", ")} и ещё ${rest}` : names.join(", ");
const names = on.slice(0, SHORT_LIST).map(toggleLabel).join(", ");
const rest = on.length - SHORT_LIST;
return rest > 0 ? t("policy.summary.more", { count: rest, names }) : names;
}
export function parentLabel(
@@ -115,17 +105,20 @@ export function parentLabel(
title: string | null
): string {
if (scopeType === "folder") {
return `у папки «${title ?? "без названия"}»`;
return t("policy.parent.folder", {
title: title ?? t("policy.parent.untitled"),
});
}
return PARENT_LABELS[scopeType] ?? "по умолчанию";
const scope = DEFAULT_SCOPES[scopeType];
return scope ? t(`policy.parent.${scope}`) : t("policy.parent.default");
}
function labelList(keys: ToggleKey[]): string {
return keys.map((key) => TOGGLE_LABELS[key]).join(", ");
return keys.map(toggleLabel).join(", ");
}
function named(keys: ToggleKey[], sign: Chip["sign"]): Chip[] {
return keys.map((key) => ({ label: TOGGLE_LABELS[key], sign }));
return keys.map((key) => ({ label: toggleLabel(key), sign }));
}
function counted(keys: ToggleKey[], sign: Chip["sign"]): Chip[] {
@@ -135,21 +128,29 @@ function counted(keys: ToggleKey[], sign: Chip["sign"]): Chip[] {
if (keys.length <= SHOWN_CHIPS) {
return named(keys, sign);
}
const word = plural(keys.length, "настройка", "настройки", "настроек");
return [{ hint: labelList(keys), label: `${keys.length} ${word}`, sign }];
return [
{
hint: labelList(keys),
label: t("policy.chip.settings", { count: keys.length }),
sign,
},
];
}
export function contentChips(rule: CaptureToggles): Chip[] {
const on = TOGGLE_KEYS.filter((key) => rule[key]);
const off = TOGGLE_KEYS.filter((key) => !rule[key]);
if (off.length === 0) {
return [{ label: "Всё включено", sign: "plus" }];
return [{ label: t("policy.chip.allOn"), sign: "plus" }];
}
if (on.length === 0) {
return [{ label: "Всё выключено", sign: "minus" }];
return [{ label: t("policy.chip.allOff"), sign: "minus" }];
}
if (off.length <= SHOWN_CHIPS) {
return [{ label: "Всё", sign: "plus" }, ...named(off, "minus")];
return [
{ label: t("policy.summary.all"), sign: "plus" },
...named(off, "minus"),
];
}
return [...counted(on, "plus"), ...counted(off, "minus")];
}
@@ -158,10 +159,10 @@ export function diffChips(rule: CaptureToggles, base: CaptureToggles): Chip[] {
const plus = TOGGLE_KEYS.filter((key) => rule[key] && !base[key]);
const minus = TOGGLE_KEYS.filter((key) => !rule[key] && base[key]);
if (plus.length > SHOWN_CHIPS && TOGGLE_KEYS.every((key) => rule[key])) {
return [{ label: "Всё включено", sign: "plus" }];
return [{ label: t("policy.chip.allOn"), sign: "plus" }];
}
if (minus.length > SHOWN_CHIPS && TOGGLE_KEYS.every((key) => !rule[key])) {
return [{ label: "Всё выключено", sign: "minus" }];
return [{ label: t("policy.chip.allOff"), sign: "minus" }];
}
return [...counted(plus, "plus"), ...counted(minus, "minus")];
}