d1ec7367a0
Root cause: when auth.me() failed during initial navigation, the catch block
called navigate('/login') without clearing _pendingLoginRedirect. The outer
finally then fired a second concurrent navigate('/login'), which held
isNavigating=true while running. If the user submitted the login form (or
iCloud Keychain autofilled credentials) before the second navigation
completed, navigate('/', user) was silently blocked by the isNavigating guard —
login appeared to succeed but the app never advanced to the dashboard.
Fix: clear _pendingLoginRedirect in the catch block so the finally handler
does not spawn the duplicate navigation.
Also adds a GET /api/v1/version endpoint (no auth required) and shows the
version on the login page, so users can verify their PWA has received the
latest cached JS.
Resolves #68
Co-authored-by: Ulas Kalayci <ulas.kalayci@googlemail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
609 lines
29 KiB
JSON
609 lines
29 KiB
JSON
{
|
||
"common": {
|
||
"save": "Сохранить",
|
||
"cancel": "Отмена",
|
||
"delete": "Удалить",
|
||
"edit": "Редактировать",
|
||
"close": "Закрыть",
|
||
"create": "Создать",
|
||
"add": "Добавить",
|
||
"back": "Назад",
|
||
"next": "Далее",
|
||
"loading": "Загрузка…",
|
||
"saving": "Сохранение…",
|
||
"required": "Это поле обязательно.",
|
||
"error": "Ошибка",
|
||
"allFieldsRequired": "Пожалуйста, заполните все поля.",
|
||
"today": "Сегодня",
|
||
"tomorrow": "Завтра",
|
||
"skipToContent": "Перейти к содержимому",
|
||
"reload": "Обновить",
|
||
"errorOccurred": "Что-то пошло не так.",
|
||
"unexpectedError": "Произошла непредвиденная ошибка.",
|
||
"errorGeneric": "Произошла ошибка.",
|
||
"updateAvailable": "Доступно обновление — перезагрузите страницу для получения последней версии.",
|
||
"titleRequired": "Заголовок обязателен",
|
||
"nameRequired": "Имя обязательно",
|
||
"contentRequired": "Содержимое обязательно",
|
||
"all": "Все",
|
||
"unknownError": "Неизвестная ошибка",
|
||
"confirm": "Подтвердить",
|
||
"undo": "Отменить"
|
||
},
|
||
"nav": {
|
||
"dashboard": "Обзор",
|
||
"tasks": "Задачи",
|
||
"calendar": "Календарь",
|
||
"meals": "Питание",
|
||
"shopping": "Покупки",
|
||
"notes": "Заметки",
|
||
"contacts": "Контакты",
|
||
"budget": "Бюджет",
|
||
"settings": "Настройки",
|
||
"main": "Главная навигация",
|
||
"navigation": "Навигация",
|
||
"quickActions": "Быстрые действия"
|
||
},
|
||
"dashboard": {
|
||
"title": "Обзор",
|
||
"greetingMorning": "Доброе утро, {{name}}",
|
||
"greetingDay": "Добрый день, {{name}}",
|
||
"greetingEvening": "Добрый вечер, {{name}}",
|
||
"allDone": "Всё готово",
|
||
"noEvents": "Нет событий",
|
||
"noPinnedNotes": "Нет закреплённых заметок",
|
||
"todayMeals": "Питание сегодня",
|
||
"allLink": "Все",
|
||
"weekLink": "Неделя",
|
||
"urgentTasksChip": "{{count}} срочная задача",
|
||
"urgentTasksChipPlural": "{{count}} срочных задач",
|
||
"eventsChip": "{{count}} событие сегодня",
|
||
"eventsChipPlural": "{{count}} событий сегодня",
|
||
"todayMealChip": "Сегодня: {{title}}",
|
||
"loadError": "Не удалось полностью загрузить панель управления.",
|
||
"weatherRefresh": "Обновить погоду",
|
||
"weatherRefreshTitle": "Обновить",
|
||
"weatherUpdated": "Погода обновлена",
|
||
"weatherFeelsLike": "Ощущается как {{temp}}° · {{humidity}}% · Ветер {{wind}} км/ч",
|
||
"fabTaskLabel": "Добавить задачу",
|
||
"fabCalendarLabel": "Добавить событие",
|
||
"fabShoppingLabel": "Добавить покупку",
|
||
"fabNoteLabel": "Добавить заметку",
|
||
"fabTask": "Задача",
|
||
"fabCalendar": "Событие",
|
||
"fabShopping": "Покупка",
|
||
"fabNote": "Заметка",
|
||
"overdue": "Просрочено",
|
||
"dueSoon": "Сегодня",
|
||
"dueTomorrow": "Завтра",
|
||
"allDay": "Весь день",
|
||
"shoppingMore": "+{{count}} ещё",
|
||
"weather": "Погода",
|
||
"customize": "Настроить",
|
||
"customizeTitle": "Настроить виджеты",
|
||
"customizeReset": "Сбросить",
|
||
"customizeSaved": "Панель сохранена",
|
||
"customizeMoveUp": "Вверх",
|
||
"customizeMoveDown": "Вниз"
|
||
},
|
||
"tasks": {
|
||
"title": "Задачи",
|
||
"newTask": "Новая задача",
|
||
"editTask": "Редактировать задачу",
|
||
"emptyTitle": "Нет задач — всё готово?",
|
||
"emptyDescription": "Создайте новые задачи с помощью кнопки +.",
|
||
"titleLabel": "Заголовок *",
|
||
"titlePlaceholder": "Что нужно сделать?",
|
||
"descriptionLabel": "Заметка",
|
||
"descriptionPlaceholder": "Дополнительные сведения…",
|
||
"priorityLabel": "Приоритет",
|
||
"categoryLabel": "Категория",
|
||
"dueDateLabel": "Срок выполнения",
|
||
"dueTimeLabel": "Время",
|
||
"assignedLabel": "Назначено",
|
||
"assignedNobody": "- Никому -",
|
||
"statusLabel": "Статус",
|
||
"priorityUrgent": "Срочно",
|
||
"priorityHigh": "Высокий",
|
||
"priorityMedium": "Средний",
|
||
"priorityLow": "Низкий",
|
||
"priorityNone": "Нет",
|
||
"statusOpen": "Открыто",
|
||
"statusInProgress": "В процессе",
|
||
"statusDone": "Выполнено",
|
||
"categoryHousehold": "Домашнее хозяйство",
|
||
"categorySchool": "Школа",
|
||
"categoryShopping": "Покупки",
|
||
"categoryRepair": "Ремонт",
|
||
"categoryHealth": "Здоровье",
|
||
"categoryFinance": "Финансы",
|
||
"categoryLeisure": "Досуг",
|
||
"categoryMisc": "Разное",
|
||
"overdue": "Просрочено",
|
||
"overdueDay": "Просрочено на {{count}}д",
|
||
"dueToday": "Срок сегодня",
|
||
"dueTomorrow": "Срок завтра",
|
||
"groupOverdue": "Просрочено",
|
||
"groupToday": "Сегодня",
|
||
"groupThisWeek": "На этой неделе",
|
||
"groupNextWeek": "На следующей неделе",
|
||
"groupLater": "Позже",
|
||
"groupNoDate": "Без даты",
|
||
"markDone": "Отметить {{title}} как выполненное",
|
||
"markOpen": "Отметить {{title}} как открытое",
|
||
"editButton": "Редактировать задачу",
|
||
"swipeOpen": "Открыть снова",
|
||
"swipeDone": "Выполнено",
|
||
"swipeEdit": "Редактировать",
|
||
"subtaskAdd": "+ Добавить подзадачу",
|
||
"subtaskToggle": "Показать подзадачи",
|
||
"subtaskMarkDone": "Отметить {{title}} как выполненное",
|
||
"deleteConfirm": "Удалить задачу и все подзадачи?",
|
||
"savedToast": "Задача сохранена.",
|
||
"createdToast": "Задача создана.",
|
||
"deletedToast": "Задача удалена.",
|
||
"loadError": "Не удалось загрузить задачу.",
|
||
"subtaskPrompt": "Подзадача:",
|
||
"kanbanOpen": "Открыто",
|
||
"kanbanInProgress": "В процессе",
|
||
"kanbanDone": "Выполнено",
|
||
"kanbanMoveToInProgress": "Перевести в работу",
|
||
"kanbanMoveToDone": "Отметить как выполненное",
|
||
"kanbanMoveToOpen": "Открыть снова",
|
||
"recurring": "Повторяющееся",
|
||
"listView": "Список",
|
||
"kanbanView": "Канбан"
|
||
},
|
||
"shopping": {
|
||
"title": "Покупки",
|
||
"noLists": "Нет списков",
|
||
"noListsDescription": "Создайте список с помощью кнопки +.",
|
||
"emptyList": "Список пуст",
|
||
"emptyListDescription": "Добавьте товары через поле ввода выше.",
|
||
"newListPrompt": "Название нового списка:",
|
||
"newListButton": "Создать новый список",
|
||
"renameListPrompt": "Новое название списка:",
|
||
"deleteListConfirm": "Удалить список «{{name}}» и все товары?",
|
||
"deletedListToast": "Список удалён.",
|
||
"itemDeletedToast": "«{{name}}» удалено.",
|
||
"itemsRemovedToast": "{{count}} товаров удалено.",
|
||
"clearChecked": "Удалить отмеченные ({{count}})",
|
||
"itemNamePlaceholder": "Добавить товар…",
|
||
"itemQtyPlaceholder": "Количество",
|
||
"itemNameLabel": "Название товара",
|
||
"itemQtyLabel": "Количество",
|
||
"categoryLabel": "Категория",
|
||
"addItemLabel": "Добавить товар",
|
||
"renameListLabel": "Переименовать список",
|
||
"deleteListLabel": "Удалить список",
|
||
"swipeBack": "Отменить",
|
||
"swipeCheck": "Отметить",
|
||
"swipeDelete": "Удалить",
|
||
"markDoneLabel": "Отметить {{name}}",
|
||
"markUndoneLabel": "Снять отметку с {{name}}",
|
||
"deleteItemLabel": "Удалить {{name}}",
|
||
"listsLoadError": "Не удалось загрузить списки.",
|
||
"itemsLoadError": "Не удалось загрузить товары.",
|
||
"catFruitVeg": "Фрукты и овощи",
|
||
"catBakery": "Выпечка",
|
||
"catDairy": "Молочные продукты",
|
||
"catMeatFish": "Мясо и рыба",
|
||
"catFrozen": "Заморозка",
|
||
"catDrinks": "Напитки",
|
||
"catHousehold": "Хозтовары",
|
||
"catDrugstore": "Аптека",
|
||
"catMisc": "Разное"
|
||
},
|
||
"meals": {
|
||
"title": "План питания",
|
||
"noMealPlanned": "Питание не запланировано",
|
||
"addMeal": "Добавить {{type}}",
|
||
"editMeal": "Редактировать приём пищи",
|
||
"addMealTitle": "Добавить приём пищи",
|
||
"deleteMeal": "Удалить приём пищи",
|
||
"transferToShoppingList": "Добавить ингредиенты в список покупок",
|
||
"today": "Сегодня",
|
||
"prevWeek": "Предыдущая неделя",
|
||
"nextWeek": "Следующая неделя",
|
||
"loadError": "Не удалось загрузить план питания.",
|
||
"typeBreakfast": "Завтрак",
|
||
"typeLunch": "Обед",
|
||
"typeDinner": "Ужин",
|
||
"typeSnack": "Перекус",
|
||
"dayMo": "Пн",
|
||
"dayDi": "Вт",
|
||
"dayMi": "Ср",
|
||
"dayDo": "Чт",
|
||
"dayFr": "Пт",
|
||
"daySa": "Сб",
|
||
"daySo": "Вс",
|
||
"dateLabel": "Дата",
|
||
"mealTypeLabel": "Приём пищи",
|
||
"titleLabel": "Название *",
|
||
"titlePlaceholder": "напр. Борщ",
|
||
"notesLabel": "Заметки",
|
||
"notesPlaceholder": "Необязательно…",
|
||
"ingredientsLabel": "Ингредиенты",
|
||
"addIngredient": "Добавить ингредиент",
|
||
"ingredientNamePlaceholder": "Ингредиент",
|
||
"ingredientQtyPlaceholder": "Количество",
|
||
"ingredientCategoryLabel": "Категория",
|
||
"ingredientCategoryDefault": "Разное",
|
||
"removeIngredient": "Удалить ингредиент",
|
||
"transferLabel": "Перенести ингредиенты в список покупок",
|
||
"transferNow": "Перенести сейчас",
|
||
"noShoppingLists": "Нет списков покупок",
|
||
"transferSuccess": "{{count}} ингредиент перенесён",
|
||
"transferSuccessPlural": "{{count}} ингредиентов перенесено",
|
||
"transferAlreadyDone": "Все ингредиенты уже перенесены",
|
||
"ingredientCount": "{{count}} ингредиент",
|
||
"ingredientCountPlural": "{{count}} ингредиентов",
|
||
"titleRequired": "Название обязательно",
|
||
"loadingIndicator": "Загрузка…",
|
||
"recipeUrlLabel": "Ссылка на рецепт (необязательно)",
|
||
"recipeUrlPlaceholder": "https://…",
|
||
"openRecipe": "Открыть рецепт"
|
||
},
|
||
"calendar": {
|
||
"title": "Календарь",
|
||
"newEvent": "Новое событие",
|
||
"editEvent": "Редактировать событие",
|
||
"addEvent": "Добавить событие",
|
||
"deleteEvent": "Удалить событие",
|
||
"noEvents": "Нет событий в выбранном периоде.",
|
||
"today": "Сегодня",
|
||
"back": "Назад",
|
||
"forward": "Вперёд",
|
||
"viewMonth": "Месяц",
|
||
"viewWeek": "Неделя",
|
||
"viewDay": "День",
|
||
"viewAgenda": "Повестка",
|
||
"allDay": "Весь день",
|
||
"allDayShort": "весь день",
|
||
"moreEvents": "+{{count}} ещё",
|
||
"weekNumberLabel": "Н{{week}} · {{month}} {{year}}",
|
||
"agendaFrom": "С {{date}}",
|
||
"titleLabel": "Заголовок *",
|
||
"titlePlaceholder": "напр. Врач",
|
||
"allDayToggle": "Весь день",
|
||
"startDateLabel": "Дата начала",
|
||
"startTimeLabel": "Время начала",
|
||
"endDateLabel": "Дата окончания",
|
||
"endTimeLabel": "Время окончания",
|
||
"fromLabel": "С",
|
||
"toLabel": "По",
|
||
"locationLabel": "Место",
|
||
"locationPlaceholder": "Необязательно",
|
||
"assignedLabel": "Назначено",
|
||
"assignedNobody": "- Никому -",
|
||
"colorLabel": "Цвет {{color}}",
|
||
"descriptionLabel": "Описание",
|
||
"descriptionPlaceholder": "Необязательно…",
|
||
"popupEdit": "Редактировать",
|
||
"deleteConfirm": "Удалить «{{title}}»?",
|
||
"createdToast": "Событие создано",
|
||
"savedToast": "Событие сохранено",
|
||
"deletedToast": "Событие удалено",
|
||
"loadError": "Не удалось загрузить события.",
|
||
"saveError": "Ошибка сохранения",
|
||
"deleteError": "Ошибка удаления",
|
||
"titleRequired": "Заголовок обязателен",
|
||
"monthJanuary": "Январь",
|
||
"monthFebruary": "Февраль",
|
||
"monthMarch": "Март",
|
||
"monthApril": "Апрель",
|
||
"monthMay": "Май",
|
||
"monthJune": "Июнь",
|
||
"monthJuly": "Июль",
|
||
"monthAugust": "Август",
|
||
"monthSeptember": "Сентябрь",
|
||
"monthOctober": "Октябрь",
|
||
"monthNovember": "Ноябрь",
|
||
"monthDecember": "Декабрь",
|
||
"dayShortSunday": "Вс",
|
||
"dayShortMonday": "Пн",
|
||
"dayShortTuesday": "Вт",
|
||
"dayShortWednesday": "Ср",
|
||
"dayShortThursday": "Чт",
|
||
"dayShortFriday": "Пт",
|
||
"dayShortSaturday": "Сб",
|
||
"dayLongSunday": "Воскресенье",
|
||
"dayLongMonday": "Понедельник",
|
||
"dayLongTuesday": "Вторник",
|
||
"dayLongWednesday": "Среда",
|
||
"dayLongThursday": "Четверг",
|
||
"dayLongFriday": "Пятница",
|
||
"dayLongSaturday": "Суббота",
|
||
"timeSuffix": ""
|
||
},
|
||
"notes": {
|
||
"title": "Заметки",
|
||
"newNote": "Новая заметка",
|
||
"editNote": "Редактировать заметку",
|
||
"addNoteLabel": "Новая заметка",
|
||
"searchPlaceholder": "Поиск по заметкам…",
|
||
"emptyTitle": "Нет заметок",
|
||
"emptyDescription": "Создайте новую заметку с помощью кнопки +.",
|
||
"noResultsTitle": "Нет результатов",
|
||
"noResultsDescription": "Ни одна заметка не содержит «{{query}}».",
|
||
"titleLabel": "Заголовок (необязательно)",
|
||
"titlePlaceholder": "Без заголовка",
|
||
"contentLabel": "Содержимое",
|
||
"contentMarkdownHint": "(Поддерживается Markdown-форматирование)",
|
||
"contentPlaceholder": "Введите заметку…",
|
||
"colorLabel": "Цвет",
|
||
"pinnedLabel": "Закрепить (отображается на панели)",
|
||
"pinAction": "Закрепить",
|
||
"unpinAction": "Открепить",
|
||
"deleteLabel": "Удалить заметку",
|
||
"deleteConfirm": "Удалить эту заметку?",
|
||
"createdToast": "Заметка создана",
|
||
"savedToast": "Заметка сохранена",
|
||
"deletedToast": "Заметка удалена",
|
||
"loadError": "Не удалось загрузить заметки.",
|
||
"formatBold": "Жирный (Ctrl+B)",
|
||
"formatItalic": "Курсив (Ctrl+I)",
|
||
"formatUnderline": "Подчёркнутый (Ctrl+U)",
|
||
"formatStrikethrough": "Зачёркнутый",
|
||
"formatHeading": "Заголовок",
|
||
"formatList": "Маркированный список",
|
||
"formatOrderedList": "Нумерованный список",
|
||
"formatChecklist": "Список задач",
|
||
"formatLink": "Ссылка",
|
||
"formatCode": "Код",
|
||
"formatQuote": "Цитата",
|
||
"formatDivider": "Разделитель"
|
||
},
|
||
"contacts": {
|
||
"title": "Контакты",
|
||
"newContact": "Новый контакт",
|
||
"editContact": "Редактировать контакт",
|
||
"addButton": "Новый",
|
||
"newContactLabel": "Новый контакт",
|
||
"searchPlaceholder": "Поиск по имени, телефону или email…",
|
||
"importButton": "Импорт",
|
||
"importLabel": "Импортировать контакт из vCard",
|
||
"importTooltip": "Импортировать vCard",
|
||
"emptyTitle": "Нет контактов",
|
||
"emptyDescription": "Добавьте новые контакты с помощью кнопки +.",
|
||
"filterAll": "Все",
|
||
"nameLabel": "Имя *",
|
||
"namePlaceholder": "Полное имя",
|
||
"categoryLabel": "Категория",
|
||
"phoneLabel": "Телефон",
|
||
"phonePlaceholder": "+7 …",
|
||
"emailLabel": "Email",
|
||
"emailPlaceholder": "имя@пример.ру",
|
||
"addressLabel": "Адрес",
|
||
"addressPlaceholder": "Улица, индекс Город",
|
||
"notesLabel": "Заметки",
|
||
"notesPlaceholder": "Необязательно…",
|
||
"callLabel": "Позвонить",
|
||
"emailActionLabel": "Email",
|
||
"mapsLabel": "Открыть в Картах",
|
||
"exportLabel": "Экспортировать в vCard",
|
||
"exportTooltip": "Экспорт vCard",
|
||
"deleteLabel": "Удалить контакт",
|
||
"deleteConfirm": "Удалить этот контакт?",
|
||
"deletePersonConfirm": "Удалить «{{name}}»?",
|
||
"savedToast": "Контакт сохранён",
|
||
"updatedToast": "Контакт обновлён",
|
||
"deletedToast": "Контакт удалён",
|
||
"importedToast": "{{name}} импортирован.",
|
||
"importError": "Ошибка импорта: {{error}}",
|
||
"vcardNoName": "В vCard нет имени.",
|
||
"catDoctor": "Врач",
|
||
"catSchool": "Школа/Детсад",
|
||
"catAuthority": "Гос. орган",
|
||
"catInsurance": "Страховая",
|
||
"catCraftsman": "Мастер",
|
||
"catEmergency": "Экстренная помощь",
|
||
"catMisc": "Разное",
|
||
"categoryDoctor": "Врач",
|
||
"categorySchool": "Школа/Детсад",
|
||
"categoryAuthority": "Гос. орган",
|
||
"categoryInsurance": "Страховая",
|
||
"categoryCraftsman": "Мастер",
|
||
"categoryEmergency": "Экстренная помощь",
|
||
"categoryOther": "Другое"
|
||
},
|
||
"budget": {
|
||
"title": "Бюджет",
|
||
"newEntry": "Новая запись",
|
||
"editEntry": "Редактировать запись",
|
||
"addEntryLabel": "Добавить запись",
|
||
"newEntryFabLabel": "Новая запись",
|
||
"currentMonth": "Текущий",
|
||
"prevMonth": "Предыдущий месяц",
|
||
"nextMonth": "Следующий месяц",
|
||
"income": "Доходы",
|
||
"expenses": "Расходы",
|
||
"balance": "Баланс",
|
||
"byCategory": "По категориям",
|
||
"transactions": "Транзакции",
|
||
"emptyTitle": "Нет записей за этот месяц",
|
||
"emptyDescription": "Добавьте записи бюджета с помощью кнопки +.",
|
||
"csvExport": "CSV",
|
||
"typeExpense": "Расход",
|
||
"typeIncome": "Доход",
|
||
"titleLabel": "Заголовок *",
|
||
"titlePlaceholder": "напр. Продукты",
|
||
"amountLabel": "Сумма *",
|
||
"amountPlaceholder": "0,00",
|
||
"categoryLabel": "Категория",
|
||
"dateLabel": "Дата *",
|
||
"recurringLabel": "Повторяющееся",
|
||
"deleteLabel": "Удалить запись",
|
||
"deleteConfirm": "Удалить эту запись?",
|
||
"deletePersonConfirm": "Удалить «{{title}}»?",
|
||
"addedToast": "Запись добавлена",
|
||
"savedToast": "Запись сохранена",
|
||
"deletedToast": "Запись удалена",
|
||
"loadError": "Не удалось загрузить бюджет.",
|
||
"trendNeutral": "— как в {{month}}",
|
||
"validAmountRequired": "Введите корректную сумму",
|
||
"dateRequired": "Дата обязательна",
|
||
"catFood": "Продукты",
|
||
"catRent": "Аренда",
|
||
"catInsurance": "Страховка",
|
||
"catMobility": "Транспорт",
|
||
"catLeisure": "Досуг",
|
||
"catClothing": "Одежда",
|
||
"catHealth": "Здоровье",
|
||
"catEducation": "Образование",
|
||
"catMisc": "Разное",
|
||
"catEarnedIncome": "Трудовой доход",
|
||
"catInvestmentIncome": "Инвестиционный доход",
|
||
"catTransferGiftIncome": "Переводы и подарки",
|
||
"catGovernmentBenefits": "Социальные пособия",
|
||
"catOtherIncome": "Прочие доходы",
|
||
"loadingIndicator": "Загрузка…"
|
||
},
|
||
"settings": {
|
||
"title": "Настройки",
|
||
"tabGeneral": "Общие",
|
||
"tabMeals": "Питание",
|
||
"tabBudget": "Бюджет",
|
||
"tabShopping": "Покупки",
|
||
"tabCalendar": "Календарь",
|
||
"tabAccount": "Аккаунт",
|
||
"tabsAriaLabel": "Разделы настроек",
|
||
"sectionDesign": "Внешний вид",
|
||
"sectionShopping": "Покупки",
|
||
"shoppingCategoriesLabel": "Категории покупок",
|
||
"shoppingCategoriesHint": "Добавляйте, переименовывайте, удаляйте или сортируйте категории.",
|
||
"shoppingCategoryPlaceholder": "Новая категория…",
|
||
"shoppingCategoryRenameHint": "Нажмите для переименования",
|
||
"shoppingCategoryRenamePrompt": "Новое название категории:",
|
||
"shoppingCategoryMoveUp": "Переместить категорию вверх",
|
||
"shoppingCategoryMoveDown": "Переместить категорию вниз",
|
||
"shoppingCategoryDelete": "Удалить категорию",
|
||
"shoppingCategoryDeleteConfirm": "Удалить категорию «{{name}}»? Существующие товары будут перемещены в следующую категорию.",
|
||
"shoppingCategoryAdded": "Категория добавлена.",
|
||
"shoppingCategoryRenamed": "Категория переименована.",
|
||
"shoppingCategoryDeleted": "Категория удалена.",
|
||
"sectionAccount": "Мой аккаунт",
|
||
"sectionCalendarSync": "Синхронизация календаря",
|
||
"sectionFamily": "Члены семьи",
|
||
"cardAppearance": "Отображение",
|
||
"themeSystem": "Система",
|
||
"themeSysLabel": "Использовать системную настройку",
|
||
"themeLight": "Светлая",
|
||
"themeLightLabel": "Светлая тема",
|
||
"themeDark": "Тёмная",
|
||
"themeDarkLabel": "Тёмная тема",
|
||
"changePassword": "Изменить пароль",
|
||
"currentPasswordLabel": "Текущий пароль",
|
||
"newPasswordLabel": "Новый пароль",
|
||
"confirmPasswordLabel": "Подтвердить новый пароль",
|
||
"savePassword": "Сохранить пароль",
|
||
"passwordMismatch": "Пароли не совпадают.",
|
||
"passwordSavedToast": "Пароль успешно изменён.",
|
||
"googleCalendar": "Google Календарь",
|
||
"appleCalendar": "Apple Calendar (iCloud)",
|
||
"syncNow": "Синхронизировать сейчас",
|
||
"disconnect": "Отключить",
|
||
"connectGoogle": "Подключить Google",
|
||
"connected": "Подключено",
|
||
"connectedLastSync": "Подключено · Последняя: {{date}}",
|
||
"notConnected": "Не подключено",
|
||
"notConfigured": "Не настроено (отсутствуют переменные .env)",
|
||
"configured": "Настроено (через .env)",
|
||
"configuredLastSync": "Настроено (через .env) · Последняя: {{date}}",
|
||
"syncSuccess": "{{provider}} синхронизирован.",
|
||
"disconnectedToast": "{{provider}} отключён.",
|
||
"googleOnlyAdmin": "Только администратор может подключить Google Календарь.",
|
||
"appleOnlyAdmin": "Только администратор может подключить Apple Calendar.",
|
||
"caldavUrlLabel": "URL сервера CalDAV",
|
||
"caldavUrlPlaceholder": "https://caldav.icloud.com",
|
||
"appleIdLabel": "Apple ID (email)",
|
||
"applePasswordLabel": "Пароль для приложения",
|
||
"applePasswordHint": "Создайте пароль на <strong>appleid.apple.com → Безопасность</strong>.",
|
||
"appleConnectBtn": "Подключить и протестировать",
|
||
"appleConnecting": "Подключение…",
|
||
"appleConnectedToast": "Apple Calendar подключён.",
|
||
"syncSuccessGoogle": "Синхронизация календаря с Google успешно подключена.",
|
||
"syncSuccessApple": "Синхронизация календаря с Apple успешно подключена.",
|
||
"syncErrorGoogle": "Не удалось подключиться к Google. Попробуйте ещё раз.",
|
||
"syncErrorApple": "Не удалось подключиться к Apple. Попробуйте ещё раз.",
|
||
"addMember": "+ Добавить участника",
|
||
"newMemberTitle": "Новый член семьи",
|
||
"usernameLabel": "Имя пользователя",
|
||
"displayNameLabel": "Отображаемое имя",
|
||
"memberPasswordLabel": "Пароль",
|
||
"colorLabel": "Цвет",
|
||
"roleLabel": "Роль",
|
||
"roleMember": "Участник",
|
||
"roleAdmin": "Администратор",
|
||
"createMember": "Создать",
|
||
"cancelAddMember": "Отмена",
|
||
"memberAddedToast": "{{name}} добавлен.",
|
||
"deleteMemberConfirm": "Удалить {{name}}?",
|
||
"memberDeletedToast": "{{name}} удалён.",
|
||
"deleteMemberLabel": "Удалить",
|
||
"logout": "Выйти",
|
||
"synchronizing": "Синхронизация…",
|
||
"googleDisconnectConfirm": "Отключить Google Календарь?",
|
||
"appleDisconnectConfirm": "Отключить Apple Calendar?",
|
||
"localeSystem": "Система",
|
||
"localeLabel": "Язык",
|
||
"languageTitle": "Язык",
|
||
"sectionMeals": "План питания",
|
||
"mealTypesLabel": "Видимые приёмы пищи",
|
||
"mealTypesHint": "В плане питания отображаются только выбранные типы приёмов пищи.",
|
||
"mealTypesSaved": "Настройки плана питания сохранены.",
|
||
"mealTypesMinOne": "Должен быть активен хотя бы один тип приёма пищи.",
|
||
"sectionBudget": "Бюджет",
|
||
"currencyLabel": "Валюта",
|
||
"currencyHint": "Устанавливает валюту для всего раздела бюджета.",
|
||
"currencySaved": "Валюта сохранена."
|
||
},
|
||
"login": {
|
||
"tagline": "Семейное планирование. Безопасно. С уважением к приватности. Открытый исходный код.",
|
||
"usernameLabel": "Имя пользователя",
|
||
"usernamePlaceholder": "имяпользователя",
|
||
"passwordLabel": "Пароль",
|
||
"passwordPlaceholder": "••••••••",
|
||
"loginButton": "Войти",
|
||
"loggingIn": "Вход…",
|
||
"tooManyAttempts": "Слишком много попыток. Подождите немного.",
|
||
"invalidCredentials": "Неверные данные для входа.",
|
||
"version": "v{{version}}"
|
||
},
|
||
"install": {
|
||
"title": "Установить Oikos",
|
||
"subtitle": "Добавить на главный экран",
|
||
"iosTip1": "Нажмите ",
|
||
"iosTip2": " → «На экран Домой»",
|
||
"installButton": "Установить",
|
||
"dismissLabel": "Закрыть"
|
||
},
|
||
"modal": {
|
||
"closeLabel": "Закрыть",
|
||
"overlayLabel": "Фон модального диалога"
|
||
},
|
||
"rrule": {
|
||
"freqNone": "Без повтора",
|
||
"freqDaily": "Ежедневно",
|
||
"freqWeekly": "Еженедельно",
|
||
"freqMonthly": "Ежемесячно",
|
||
"dayMo": "Пн",
|
||
"dayTu": "Вт",
|
||
"dayWe": "Ср",
|
||
"dayTh": "Чт",
|
||
"dayFr": "Пт",
|
||
"daySa": "Сб",
|
||
"daySu": "Вс",
|
||
"labelRepeat": "Повтор",
|
||
"labelEvery": "Каждые",
|
||
"labelOnDays": "В эти дни",
|
||
"labelUntil": "Заканчивается (необязательно)",
|
||
"unitDay": "день",
|
||
"unitDays": "дней",
|
||
"unitWeek": "неделю",
|
||
"unitWeeks": "недель",
|
||
"unitMonth": "месяц",
|
||
"unitMonths": "месяцев"
|
||
}
|
||
}
|