{
"forms": {
"upload_dir_error": "Ошибка при создании папки загрузки",
"file_create_error": "Ошибка при создании файла",
"multipart_stream_error": "Ошибка в потоке multipart",
"file_write_error": "Ошибка при записи файла",
"required": "Это поле обязательно для заполнения",
"too_short": "Слишком короткое (мин {})",
"too_long": "Слишком длинное (макс {})",
"email_invalid": "Неверный формат email адреса",
"url_invalid": "Пожалуйста, введите корректный URL",
"phone_invalid": "Неверный номер телефона (цифры, +, пробелы, дефисы, 7-15 цифр)",
"hash_error": "Ошибка хеширования: {}",
"password_empty": "Пароль не может быть пустым",
"filter_invalid_value": "Фильтр static/media получил неверное значение ({}) вместо пути к файлу.",
"number_invalid": "Неверное число",
"number_required": "Обязательно",
"integer_required": "Должно быть целым числом",
"decimal_required": "Должно быть в десятичном формате",
"min_value": "Требуется мин {}",
"max_value": "Превышен макс {}",
"precision_max": "Максимальная точность {} цифр после запятой",
"precision_min": "Минимальная точность {} цифр после запятой",
"color_invalid": "Неверный цвет (формат: #RRGGBB или #RGB)",
"color_no_hash": "Цвет должен начинаться с #",
"color_bad_hex": "Содержит не шестнадцатеричные символы",
"slug_invalid": "Неверный slug",
"slug_no_dash": "Slug не должен начинаться или заканчиваться дефисом",
"uuid_invalid": "Неверный формат UUID (ожидается: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)",
"json_invalid": "Неверный JSON: {}",
"ipv4_only": "Принимаются только IPv4 адреса",
"ipv6_only": "Принимаются только IPv6 адреса",
"ip_invalid": "Неверный IP адрес",
"date_invalid": "Неверный формат даты",
"date_too_old": "Слишком старая (мин : {})",
"date_too_far": "Слишком далеко (макс : {})",
"time_invalid": "Неверный формат времени",
"file_required": "Пожалуйста, выберите хотя бы один файл",
"data_invalid": "Недопустимое значение для «{}»",
"data_required": "«{}» обязательно",
"data_password": "Не удалось захешировать пароль «{}»; ничего не сохранено",
"file_extension_blocked": "Файл '{}' не разрешён. Разрешённые расширения: {}",
"finalize_error": "Ошибка при финализации поля '{}': {}",
"template_missing": "Отсутствует шаблон: {}",
"render_js_error": "Ошибка рендеринга JS: {}",
"tera_not_configured": "Tera не настроен",
"config_not_found": "Конфигурация не найдена в расширениях",
"hint_slug": "Формат: буквы-цифры-дефисы",
"hint_uuid": "Формат: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"hint_json": "Требуется корректный формат JSON",
"hint_ip_v4": "Формат IPv4: 192.168.1.1",
"hint_ip_v6": "Формат IPv6: 2001:0db8:85a3::8a2e:0370:7334",
"hint_ip": "Формат IPv4 или IPv6",
"validation_overflow": "Обнаружено переполнение стека: бесконечная рекурсия в валидации",
"choice_invalid": "Неверный выбор",
"choice_invalid_value": "Неверный выбор: {}",
"select_required": "Пожалуйста, выберите опцию",
"checkbox_required": "Пожалуйста, выберите хотя бы одну опцию",
"multipart_error": "Ошибка multipart",
"body_error": "Ошибка чтения тела запроса",
"aegis_query_error": "Ошибка разбора строки запроса: {}",
"aegis_urlencoded_error": "Ошибка разбора urlencoded тела: {}",
"aegis_json_error": "Ошибка разбора JSON тела: {}",
"auth_required": "Требуется аутентификация",
"role_insufficient": "Недостаточно прав",
"unknown_group": "GuardRules: несуществующие группы в roles([...]): {}",
"time_too_old": "Слишком рано (мин : {})",
"time_too_far": "Слишком поздно (макс : {})",
"datetime_too_old": "Слишком рано (мин : {})",
"datetime_too_far": "Слишком поздно (макс : {})",
"duration_invalid": "Неверная длительность (ожидается количество секунд)",
"duration_too_short": "Минимальная длительность: {} секунд",
"duration_too_long": "Максимальная длительность: {} секунд",
"file_max_count": "Разрешено максимум {} файлов",
"file_too_large": "Файл '{}' слишком большой ({}МБ > макс {}МБ)",
"file_invalid_image": "Файл '{}' не является корректным изображением",
"image_too_wide": "Изображение '{}' слишком широкое ({}px > {}px)",
"image_too_tall": "Изображение '{}' слишком высокое ({}px > {}px)",
"boolean_required": "Вы должны принять это поле",
"slug_unicode_invalid": "Разрешены только буквы, цифры, дефисы и подчёркивания",
"unique_field_taken": "Этот {} уже используется.",
"unique_value_taken": "Значение поля '{}' уже используется.",
"unique_constraint_violated": "Нарушено ограничение уникальности.",
"db_error": "Ошибка БД: {}",
"text_field_too_large": "Поле слишком большое (макс 1 МБ)",
"upload_too_large": "Файл слишком большой (макс {}МБ)"
},
"csrf": {
"missing": "Отсутствует CSRF токен",
"invalid": "Неверный CSRF токен",
"invalid_or_missing": "Неверный или отсутствующий CSRF токен",
"forbidden": "Неверный CSRF токен",
"session_write_error": "Ошибка записи сессии"
},
"error": {
"source": "Источник: {}",
"AppError": "Ошибка приложения",
"build": "Ошибка сборки: {}",
"internal": "Внутренняя ошибка",
"forbidden": "Доступ запрещён",
"not_found": "Ресурс не найден",
"validation": "Ошибка валидации: {}",
"database": "Ошибка базы данных: {}",
"io": "Ошибка ввода-вывода: {}",
"template": "Ошибка шаблона: {}",
"custom": "Пользовательская ошибка: {}",
"title": {
"bad_request": "Неверный запрос",
"not_found": "Страница не найдена",
"forbidden": "Доступ запрещён",
"validation": "Ошибка валидации",
"database": "Ошибка базы данных",
"template": "Ошибка рендеринга шаблона",
"internal": "Внутренняя ошибка сервера"
},
"invalid_query": "Недопустимые параметры запроса: {}",
"path_not_found": "Запрошенный путь '{}' не найден",
"internal_occurred": "Произошла внутренняя ошибка",
"context_occurred": "Произошла ошибка AppError"
},
"title": {
"template": "Ошибка шаблона в '{}'"
},
"build": {
"subscriber_already_installed": "Tracing subscriber уже установлен; конфигурация логов Runique неактивна (RUST_LOG / with_log не действуют)",
"external_outputs_ignored": "`with_log(|l| l.external())` установлен; настроенные выходы логов игнорируются (приложение владеет subscriber)",
"validation_failed": "Ошибка валидации сборки: {}",
"check_failed": "Ошибка сборки с {} ошибками проверки",
"template_failed": "Ошибка загрузки шаблона: {}",
"driver_not_enabled": "Драйвер {} не включён: Runique скомпилирован без feature '{}'.\n\nВ Cargo.toml вашего проекта:\nrunique = { version = \"{}\", features = [\"{}\"] }\n\nДля CLI runique:\ncargo install runique --features {} --locked --force\n\nЧтобы поддерживать все СУБД, используйте feature 'all-databases'.",
"db_missing": "Требуется подключение к базе данных при включённой функции 'orm'",
"component_not_ready": "Компонент '{}' не готов",
"check": {
"db_required": "Требуется подключение или конфигурация базы данных (включена feature `orm`)",
"db_required_hint": "Добавьте .with_database(db) или .with_database_config(config) в цепочку построения",
"admin_prefix_empty": "Префикс маршрута админки не может быть пустым",
"admin_prefix_empty_hint": "Используйте .prefix(\"/admin\") или оставьте значение по умолчанию",
"extra_route_unknown": "Дополнительный маршрут `{}` ссылается на ресурс `{}`, который не зарегистрирован",
"extra_route_unknown_hint": "Используйте ключ ресурса, объявленного в admin!{}",
"cache_control_invalid": "Недопустимое значение заголовка Cache-Control: '{}'",
"cache_control_invalid_hint": "Используйте только видимые символы ASCII (без управляющих символов и переводов строки).",
"media_root_unusable": "Не удаётся создать каталог MEDIA_ROOT '{}' или получить к нему доступ: {}",
"media_root_unusable_hint": "Укажите в .env абсолютный путь с правом записи для MEDIA_ROOT (например, MEDIA_ROOT=/var/www/myapp/media) и убедитесь, что у процесса есть право записи.",
"secret_key_weak": "SECRET_KEY отсутствует, пуст, имеет значение по умолчанию или короче 32 символов",
"secret_key_weak_hint": "Задайте в .env для SECRET_KEY случайную строку не короче 32 символов (CLI `runique` может её сгенерировать)",
"public_url_missing": "Публичный URL не задан: ссылки сброса строились бы из заголовка Host запроса",
"public_url_missing_hint": "Задайте его в builder: .with_public_url(\"https://mysite.com\")",
"acme_domain_missing": "ACME_ENABLED=true, но ACME_DOMAIN не задан",
"acme_domain_missing_hint": "Задайте в .env для ACME_DOMAIN ваш производственный домен",
"acme_email_missing": "ACME_ENABLED=true, но ACME_EMAIL не задан",
"acme_email_missing_hint": "Задайте в .env для ACME_EMAIL ваш контактный email для Let's Encrypt",
"suggestion": "Рекомендация",
"context": "Контекст"
}
},
"server": {
"operational": "Runique работает",
"launched": "Сервер запущен на {}",
"connected_db": "Подключено к базе данных {} -> {}",
"stop_hint": "ctrl + c для остановки",
"shutting_down": "Завершение работы сервера Runique...",
"acme_not_compiled": "ACME_ENABLED=true, но функция `acme` не скомпилирована.",
"acme_add_feature": "Добавьте функцию `acme` в ваш Cargo.toml.",
"test_utils_feature_enabled": "Функция `test-utils` скомпилирована в этой сборке — убедитесь, что она указана в [dev-dependencies], а не в [dependencies], перед развёртыванием в продакшене."
},
"middleware": {
"bad_request": "Неверный запрос",
"slot_collision": "Коллизия слота middleware Runique: «{}» и «{}» оба используют слот {}. Зарегистрируйте меньше пользовательских middleware или задайте этому явный слот."
},
"html": {
"400_title": "400",
"400_text": "Неверный запрос: параметры адреса недействительны.",
"404_title": "404",
"404_text": "Страница не найдена",
"500_title": "500",
"500_text": "На сервере произошла ошибка",
"500_notice": "Наша команда уведомлена и работает над проблемой.",
"429_title": "429",
"429_text": "Слишком много запросов. Пожалуйста, подождите немного и повторите попытку.",
"503_title": "503",
"503_text": "Сервис временно недоступен из-за высокой нагрузки. Пожалуйста, повторите попытку позже.",
"back_home": "Вернуться на главную",
"critical_error_title": "Критическая ошибка",
"critical_error_text": "Система обработки ошибок сама столкнулась с ошибкой.",
"critical_error_contact": "Эта ситуация никогда не должна была произойти. Пожалуйста, свяжитесь с системным администратором."
},
"debug": {
"stack_trace_title": "Подробная трассировка ошибки",
"stack_trace_tip": "Самая верхняя ошибка (уровень 0) обычно является корневой причиной. Последующие ошибки показывают, как ошибка распространилась в коде."
},
"flash": {
"welcome": "Добро пожаловать, {}, ваш аккаунт создан!",
"fix_errors": "Пожалуйста, исправьте ошибки",
"success_demo": "Это сообщение об успехе.",
"info_demo": "Это информационное сообщение.",
"warning_demo": "Это предупреждающее сообщение.",
"error_demo": "Это сообщение об ошибке."
},
"cli": {
"creating_project": "Создание проекта '{}'...",
"admin_detected": "Админка обнаружена → генерация кода админки",
"add_admin_hint": "Добавьте .with_admin(...) в ваш builder для активации панели администратора.",
"daemon_error": "[Daemon] Ошибка: {}",
"cargo_run_failed": "Приложение не запустилось корректно (cargo run)",
"file_not_found": "Файл не найден: {}\nУбедитесь, что вы находитесь в корне вашего проекта Runique.",
"admin_not_found": "Файл admin не найден: {}\nСоздайте src/admin.rs с макросом admin!{}.",
"name_empty": "Имя проекта не может быть пустым",
"name_invalid": "Имя проекта должно содержать только буквы, цифры, _ или -",
"name_dash": "Имя проекта не может начинаться с -",
"folder_exists": "Папка '{}' уже существует",
"cargo_run_expect": "Не удалось запустить cargo run",
"project_created": "Проект '{}' успешно создан!",
"getting_started": "Для начала:",
"cd_hint": "cd {}",
"cargo_run_hint": "cargo run",
"fmt_failed": "cargo fmt завершился с ошибкой — форматирование пропущено: {}"
},
"daemon": {
"unable_read": "Невозможно прочитать: {}",
"parse_error": "Ошибка разбора: {}",
"no_resource": "Нет ресурсов в admin!{} — нечего генерировать",
"operational": "Daemon работает → src/admins/admin.rs",
"generation_error": "Ошибка генерации: {}",
"generated_header": "СГЕНЕРИРОВАНО АВТОМАТИЧЕСКИ — НЕ РЕДАКТИРОВАТЬ ВРУЧНУЮ",
"generated_notice": "Создано `runique start` из src/admin.rs. Любые изменения будут перезаписаны."
},
"macro": {
"named_fields_only": "Только структуры с именованными полями",
"structs_only": "Работает только со структурами",
"forms_field_required": "Структура '{}' должна иметь поле 'Forms'",
"field_no_name": "Поле без имени",
"model_form_named_only": "DeriveModelForm: только структуры с именованными полями",
"model_form_structs_only": "DeriveModelForm: только структуры"
},
"parser": {
"multiple_admin_blocks": "admin!: в одном файле допустим только один блок admin! (первый блок в строке {}, второй в строке {}) — объедините их",
"title_required": "admin!: 'title' обязателен",
"list_display_exclude_exclusive": "admin!: 'list_display' и 'list_exclude' взаимно исключают друг друга"
},
"TemplateMessage": {
"debug_info_title": "Отладочная информация",
"debug_field_title": "Заголовок",
"debug_field_count": "Количество полей",
"debug_error_count": "Ошибки",
"debug_main_message": "Основное сообщение",
"debug_root_cause": "Корневая причина",
"debug_details": "Дополнительные детали",
"debug_request_info": "Информация о запросе",
"debug_http_method": "HTTP метод",
"debug_path": "Путь",
"debug_query_params": "Параметры запроса",
"debug_http_headers": "HTTP заголовки",
"debug_template_info": "Информация о шаблоне",
"debug_template_name": "Имя шаблона",
"debug_error_line": "Строка ошибки",
"debug_template_source": "Исходный код шаблона",
"debug_available_templates": "Доступные шаблоны",
"debug_stack_trace_title": "Подробная трассировка ошибки",
"debug_stack_trace_tip": "Самая верхняя ошибка (уровень 0) обычно является корневой причиной. Последующие ошибки показывают, как ошибка распространилась в коде.",
"debug_environment": "Окружение",
"debug_debug_mode": "Режим отладки",
"debug_enabled": "Включено",
"debug_disabled": "Отключено",
"debug_rust_version": "Версия Rust",
"debug_app_version": "Версия приложения",
"debug_status_code": "Код статуса",
"debug_header_name": "Имя",
"debug_header_value": "Значение"
},
"admin": {
"group": "Группа",
"groups": "Группы",
"resource": "Ресурс",
"resources": "Ресурсы",
"can_create": "Создать",
"can_read": "Чтение",
"can_update": "Изменение",
"can_delete": "Удалить",
"can_update_own": "Изменение",
"can_delete_own": "Удалить",
"name": "Имя",
"username": "Имя пользователя",
"email": "Email",
"staff": "Сотрудник",
"superuser": "Суперпользователь",
"active": "Активен",
"user": {
"username_too_short": "Имя пользователя слишком короткое (минимум 3 символа)",
"invalid_email": "Неверный формат email адреса",
"not_activated": "Эта учётная запись ещё не активирована пользователем: это произойдёт, когда он выберет пароль по полученному письму."
},
"login": {
"title": "Вход",
"subtitle": "Войдите для доступа к панели администратора",
"label_username": "Имя пользователя",
"label_password": "Пароль",
"btn_submit": "Войти",
"error_session": "Ошибка при открытии сессии.",
"error_credentials": "Неверные учётные данные или недостаточно прав.",
"error_locked": "Слишком много попыток. Аккаунт временно заблокирован. Повторите через {} секунд."
},
"logout": {
"success": "Выход выполнен успешно."
},
"access": {
"insufficient_rights": "Недостаточно прав для доступа к администрированию"
},
"dashboard": {
"title": "Панель управления",
"subtitle": "Обзор приложения",
"card_resources": "Ресурсы",
"th_resource": "Ресурс",
"th_key": "Ключ",
"th_permissions": "Разрешения",
"th_actions": "Действия",
"btn_list": "Список",
"btn_create": "Создать",
"see_list": "Посмотреть список →",
"empty_title": "Нет зарегистрированных ресурсов",
"empty_desc": "Объявите ваши ресурсы в src/admin.rs с макросом admin!{{}} затем запустите runique start",
"kpi_resources": "Ресурсы",
"kpi_entries": "Всего записей",
"kpi_largest": "Наибольшая",
"th_count": "Записи"
},
"list": {
"breadcrumb_admin": "Администрирование",
"entries_count_one": "запись",
"entries_count_many": "записей",
"btn_create": "Создать",
"th_id": "id",
"th_actions": "Действия",
"bool_true": "Да",
"bool_false": "Нет",
"btn_detail": "Детали",
"btn_edit": "Изменить",
"btn_delete": "Удалить",
"confirm_delete": "Действительно удалить?",
"empty_title": "Нет записей",
"empty_desc": "Начните с создания элемента.",
"btn_create_first": "Создать первый",
"search_placeholder": "Поиск..."
},
"create": {
"title": "Создать",
"breadcrumb": "Создать",
"card_info": "Информация",
"no_fields": "Пока нет доступных полей.",
"btn_cancel": "Отмена",
"btn_submit": "Создать",
"success": "Запись успешно создана!"
},
"edit": {
"title": "Изменить",
"breadcrumb": "Изменить",
"card_info": "Информация",
"no_fields": "Пока нет доступных полей.",
"btn_cancel": "Отмена",
"btn_submit": "Сохранить",
"success": "Запись успешно обновлена!"
},
"detail": {
"title": "Детали",
"breadcrumb": "Детали",
"entry_label": "Запись",
"btn_list": "← Список",
"btn_edit": "Изменить",
"btn_delete": "Удалить",
"confirm_delete": "Удалить эту запись?",
"btn_reset_password": "Сбросить пароль",
"btn_reset_password_short": "Сбросить"
},
"reset_password": {
"btn": "Сбросить пароль",
"success_email": "Reset link sent to {}.",
"success_link": "Reset link (mailer not configured): {}",
"error_no_email": "No email field found for this user.",
"error_send": "Error sending email: {}",
"email_subject": "Сброс пароля",
"email_title": "Сброс пароля",
"email_greeting": "Здравствуйте,",
"email_body": "Нажмите на ссылку, чтобы сбросить пароль (действительна 1 час):",
"email_btn": "Сбросить пароль",
"email_ignore": "Если вы не запрашивали сброс, проигнорируйте это сообщение."
},
"user_created": {
"email_subject": "Добро пожаловать — установите пароль",
"email_sent": "Приветственное письмо отправлено на {}.",
"email_greeting": "Добро пожаловать,",
"email_body": "Для вас создан аккаунт. Нажмите на ссылку, чтобы установить пароль:",
"email_btn": "Установить пароль",
"email_validity": "Ссылка действительна 1 час. Если вы не ожидали этого сообщения, проигнорируйте его."
},
"delete": {
"title": "Удалить",
"breadcrumb": "Удалить",
"heading": "Подтвердить удаление",
"btn_cancel": "← Отмена",
"btn_confirm": "Да, удалить безвозвратно",
"success": "Запись успешно удалена!",
"warning": {
"title": "Внимание!",
"desc": "Вы собираетесь удалить запись",
"of": "ресурса",
"irreversible": "Это действие необратимо."
},
"not_found": "Ресурс не найден."
},
"bulk": {
"no_selection": "Элементы не выбраны.",
"no_field_selected": "Ни одно поле не изменено.",
"delete_success": "элемент(ов) удалено.",
"update_success": "элемент(ов) обновлено."
},
"base": {
"title": "Администрирование",
"breadcrumb": "Админ",
"toggle": "Свернуть меню",
"logout_title": "Выход",
"theme_toggle": "Сменить тему",
"back_to_site": "← Сайт"
},
"superuser_wizard": {
"title": "=== Создать суперпользователя ===",
"algo_prompt": "[1/5] Алгоритм хэширования",
"algo_argon2": "Argon2 (рекомендуется)",
"algo_bcrypt": "Bcrypt",
"algo_scrypt": "Scrypt",
"algo_custom": "Пользовательский провайдер",
"provider_path": "Путь к провайдеру",
"invalid_path": "Неверный путь.",
"username_prompt": "[2/5] Имя пользователя",
"username_empty": "Имя пользователя не может быть пустым.",
"username_taken": "Пользователь с таким именем уже существует.",
"email_prompt": "[3/5] Email",
"email_invalid": "Недействительный email.",
"email_taken": "Пользователь с таким email уже существует.",
"password_prompt": "[4/5] Пароль",
"password_too_short": "Пароль должен содержать не менее 12 символов.",
"password_weak": "Пароль должен содержать хотя бы одну строчную букву, одну заглавную букву, одну цифру и один специальный символ.",
"confirm_prompt": "[5/5] Подтвердите пароль",
"password_mismatch": "Пароли не совпадают. Попробуйте снова.",
"review_algo": " Алгоритм : {}",
"review_username": " Логин : {}",
"review_email": " Email : {}",
"review_password": " Пароль : ••••••••",
"review_action": "Действие",
"confirm_create": "Подтвердить и создать",
"change_algo": "Изменить алгоритм",
"modify_password": "Изменить пароль",
"success": "✓ Суперпользователь успешно создан!",
"id_line": " ID : {}",
"username_line": " Логин : {}",
"email_line": " Email : {}"
},
"builtin": {
"invalid_id": "Недопустимый идентификатор.",
"droit_resource_required": "Пожалуйста, выберите хотя бы один ресурс.",
"droit_exists": "Право \"{}\" уже существует.",
"groupe_exists": "Группа с именем \"{}\" уже существует.",
"user_username_exists": "Имя пользователя \"{}\" уже занято.",
"user_email_exists": "Адрес электронной почты \"{}\" уже зарегистрирован."
}
},
"makemigrations": {
"destructive_detected": "Обнаружены деструктивные изменения:",
"destructive_require_force": "Используйте --force для применения этих деструктивных изменений.",
"long_identifier_detected": "Сгенерированные SQL-идентификаторы слишком длинные (лимит MariaDB/MySQL: 64 символа):",
"long_identifier_rename_required": "Сократите имена таблиц/столбцов — Runique не обрезает идентификаторы автоматически.",
"files_ready": "{} файл(ов) готов(о) к миграции.",
"snapshots_upgraded": "Обновлено снимков: {} — теперь они хранят длину столбцов (без миграции)."
},
"migrate": {
"applying": "Применение миграций из '{}'...",
"complete_up": "Миграция завершена.",
"crate_missing": "Крейт миграций не найден: в '{}' нет Cargo.toml."
},
"reset": {
"forgot_title": "Забыли пароль",
"reset_title": "Новый пароль",
"success_title": "Пароль сброшен",
"email_label": "Адрес электронной почты",
"new_password_label": "Новый пароль",
"confirm_label": "Подтвердите пароль",
"email_mismatch": "Адрес электронной почты не соответствует ссылке.",
"invalid_link": "Недействительная ссылка.",
"invalid_or_expired": "Ссылка для сброса недействительна или истекла.",
"password_min_length": "Пароль должен содержать не менее {} символов.",
"password_weak": "Пароль должен содержать заглавную букву, строчную букву, цифру и специальный символ (!@#$%...).",
"password_mismatch": "Пароли не совпадают.",
"check_inbox": "Если этот адрес связан с учётной записью, вы получите письмо с дальнейшими инструкциями.",
"blocked_subject": "Ваша учётная запись заблокирована",
"blocked_body": "<p>Здравствуйте, {}!</p><p>Для вашей учётной записи был запрошен сброс пароля, но она заблокирована. Обратитесь к администратору сайта, чтобы разблокировать её.</p><p>Если вы не делали этот запрос, проигнорируйте это письмо.</p>",
"email_subject": "Сброс пароля",
"email_body": "<p>Здравствуйте, {},</p><p>Перейдите по ссылке ниже для сброса пароля (действительна 1 час):</p><p><a href=\"{}\">{}</a></p>"
},
"permission": {
"col": {
"id": "ID",
"can_create": "Создание",
"can_delete": "Удаление",
"can_delete_own": "Удаление (своё)",
"can_read": "Чтение",
"can_update": "Изменение",
"can_update_own": "Изменение (своё)",
"groupes": "Группы",
"resource_key": "Ресурс",
"actions": "Действия"
}
},
"runique_test": {
"connect_failed": "не удалось подключиться: {}",
"begin_failed": "не удалось открыть тестовую транзакцию: {}",
"env_read_failed": "не удалось прочитать {}: {}",
"env_parse_failed": "не удалось разобрать {}: {}",
"env_line_malformed": "не удалось разобрать {}: строка некорректна в символе {} (строка не показана, в ней может быть пароль)",
"no_panic_message": "нет сообщения",
"query_failed": "ошибка",
"panicked": "паника: {}",
"rollback_failed": "откат: {}",
"test_failed": "{} не прошёл, см. вывод выше",
"clone_outlived": "клон тестового соединения пережил обработчик; транзакция откатится, когда этот клон будет освобождён",
"not_a_transaction": "тест выполнялся вне транзакции, поэтому откатить ничего не удалось",
"nested": "runique_test нельзя запускать внутри другого runique_test: он бы бесконечно ждал собственного вызывающего",
"timed_out": "обработчик не завершился за {} с: взаимная блокировка или строка, заблокированная другим соединением? RUNIQUE_TEST_TIMEOUT в env-файле меняет лимит",
"bad_timeout": "{} должен быть целым числом секунд больше 0, получено \"{}\"",
"transaction_ended": "транзакция теста была завершена изнутри теста (COMMIT или DDL в MariaDB/MySQL): всё записанное до этого теперь осталось в базе",
"swallowed_failures": "неудачных запросов: {}, но обработчик всё равно вернул Ok: где-то проглочена ошибка (оборачивайте ожидаемые ошибки в expect_db_error)",
"rollback_timed_out": "откат не завершился за {} с",
"expected": "ожидаемо",
"not_refused": "база приняла то, что тест ожидал увидеть отклонённым",
"no_db_config": "в env-файле нет ни DATABASE_URL, ни DB_ENGINE: тестовая база должна быть указана в нём, из оболочки ничего не берётся",
"in_memory": "в памяти: каждый тест начинается с пустой базы"
},
"test_runner": {
"no_cargo_toml": "Здесь нет Cargo.toml: запустите `runique test` из корня вашего проекта.",
"test_utils_missing": "Фича `test-utils` не включена для runique в Cargo.toml.\nДобавьте её как dev-dependency, чтобы она никогда не попала в релизную сборку:\n cargo add --dev runique --features test-utils",
"test_utils_shipped": "Cargo.toml включает `test-utils` вне [dev-dependencies], поэтому тестовый builder попадёт в вашу релизную сборку.\nУдалите её из [dependencies] (и из всех записей [features]), затем добавьте только как dev-dependency:\n cargo add --dev runique --features test-utils",
"no_mod_file": "Нет src/runique_test/mod.rs: создайте его и объявите в нём каждый тестовый файл (`mod user;`).",
"module_not_declared": "src/main.rs не объявляет тестовый модуль. Добавьте:\n #[cfg(test)]\n mod runique_test;",
"module_not_gated": "Модуль runique_test не закрыт `cfg(test)`, поэтому попадёт в каждую сборку.\nПоставьте `#[cfg(test)]` прямо над `mod runique_test;` в src/main.rs.",
"file_not_declared_warning": "предупреждение: src/runique_test/{}.rs не объявлен в mod.rs, поэтому его тесты не будут запущены. Добавьте `mod {};` в mod.rs.",
"no_test_file": "Нет src/runique_test/{}.rs. Тестовые файлы: {}",
"file_not_declared": "src/runique_test/{}.rs не объявлен в mod.rs: добавьте в него `mod {};`.",
"cargo_spawn_failed": "Не удалось запустить cargo.",
"output_failed": "Не удалось показать вывод cargo.",
"cargo_wait_failed": "cargo test завершился некорректно.",
"tests_failed": "cargo test завершился с ошибкой, см. вывод выше.",
"build_failed": "cargo не смог собрать тесты, см. ошибки выше.",
"no_such_test": "Нет теста \"{}\" в {}.rs. Доступные тесты: {}",
"dir_read_failed": "Не удалось прочитать {}"
},
"auth": {
"login_cannot_sign_in": "Эта учётная запись не может войти: она неактивна или ни разу не активирована.",
"login_session_failed": "Не удалось сохранить сессию: {}"
}
}