8b886ddf2b
Adds an opt-in "auto_backup_before_deploy" setting that triggers a "pre-deploy" backup at the start of every project deploy via the deploy pipeline (covers both the async HTTP path and the sync poller/webhook path). Failures are logged to the deploy log but do not abort — missing a backup is preferable to refusing to ship a fix. - store: settings.auto_backup_before_deploy column + scan/update wiring - backup: accept "pre-deploy" as a valid backup_type - deployer: small PreDeployBackuper interface, hooked into runDeploy right after settings load and before any state-mutating work - api: settings request/response surface the new flag - web: ToggleSwitch on the backup settings page; "Pre-deploy" badge variant in the backup list (badge-warning so it stands out) - i18n: en/ru strings for the toggle, help text, and badge label
1233 lines
70 KiB
JSON
1233 lines
70 KiB
JSON
{
|
||
"app": {
|
||
"name": "Tinyforge",
|
||
"version": "v0.1"
|
||
},
|
||
"layout": {
|
||
"serviceStatus": "Состояние служб"
|
||
},
|
||
"health": {
|
||
"connected": "подключён",
|
||
"disconnected": "отключён",
|
||
"rawError": "Технические детали",
|
||
"retryNow": "Проверить сейчас"
|
||
},
|
||
"nav": {
|
||
"dashboard": "Панель",
|
||
"projects": "Проекты",
|
||
"deploy": "Деплой",
|
||
"proxies": "Прокси",
|
||
"events": "События",
|
||
"settings": "Настройки",
|
||
"logout": "Выйти",
|
||
"dns": "DNS-записи",
|
||
"sites": "Сайты",
|
||
"stacks": "Стеки"
|
||
},
|
||
"dashboard": {
|
||
"title": "Панель управления",
|
||
"quickDeploy": "Быстрый деплой",
|
||
"totalProjects": "Всего проектов",
|
||
"runningInstances": "Запущенных экземпляров",
|
||
"failedInstances": "Сбойных экземпляров",
|
||
"projects": "Проекты",
|
||
"retry": "Повторить",
|
||
"noProjects": "Проектов пока нет.",
|
||
"addFirst": "Добавьте первый проект",
|
||
"loadFailed": "Не удалось загрузить панель",
|
||
"staleContainers": "Устаревшие контейнеры",
|
||
"unusedImagesWarning": "Неиспользуемые Docker-образы занимают дисковое пространство",
|
||
"unusedImages": "неиспользуемых образов",
|
||
"staticSites": "Статические сайты",
|
||
"totalSites": "Всего сайтов",
|
||
"deployedSites": "развёрнуто",
|
||
"failedSites": "с ошибкой",
|
||
"noSites": "Статических сайтов пока нет.",
|
||
"addFirstSite": "Разверните первый сайт",
|
||
"viewAllSites": "Все сайты",
|
||
"systemHealth": "Состояние системы",
|
||
"daemons": "Демоны",
|
||
"systemResources": "Системные ресурсы",
|
||
"systemResourcesSubtitle": "CPU, память, диск и топ потребителей"
|
||
},
|
||
"resources": {
|
||
"cpuCores": "Ядра CPU",
|
||
"memory": "Память",
|
||
"running": "Запущено",
|
||
"dockerDisk": "Диск Docker",
|
||
"workloadUtilization": "Использование нагрузкой",
|
||
"windowMinutes": "{n} минут",
|
||
"windowHours": "{n} часов",
|
||
"noSamples": "Пока нет данных — сбор идёт каждые {interval}с.",
|
||
"collectionDisabled": "Сбор статистики отключён. Включите его в Настройках, чтобы заполнить график.",
|
||
"diskImages": "Образы",
|
||
"diskContainers": "Контейнеры",
|
||
"diskVolumes": "Тома",
|
||
"diskBuildCache": "Кэш сборки",
|
||
"reclaimable": "{size} можно освободить",
|
||
"topConsumers": "Топ потребителей",
|
||
"byCpu": "по CPU",
|
||
"byMemory": "по памяти",
|
||
"noRunning": "Нет запущенных контейнеров.",
|
||
"instance": "экземпляр",
|
||
"site": "сайт",
|
||
"showHistory": "Показать историю",
|
||
"hideHistory": "Скрыть историю",
|
||
"cpuSeries": "CPU %",
|
||
"memorySeries": "Память %",
|
||
"loading": "Загрузка…",
|
||
"sectionTitle": "Ресурсы",
|
||
"showLogs": "Показать логи",
|
||
"hideLogs": "Скрыть логи",
|
||
"dockerUnavailable": "Docker недоступен. Проверьте, что демон запущен."
|
||
},
|
||
"statsSettings": {
|
||
"intervalLabel": "Интервал сбора статистики (с)",
|
||
"intervalHelp": "Как часто собираются замеры ресурсов. 0 отключает сбор. Диапазон: 5–300с.",
|
||
"retentionLabel": "Хранение статистики (часы)",
|
||
"retentionHelp": "Как долго хранятся замеры ресурсов. 0 отключает сбор. Диапазон: 0–24ч."
|
||
},
|
||
"projects": {
|
||
"title": "Проекты",
|
||
"addProject": "Добавить проект",
|
||
"cancel": "Отмена",
|
||
"newProject": "Новый проект",
|
||
"name": "Название",
|
||
"image": "Образ",
|
||
"port": "Порт",
|
||
"registry": "Реестр",
|
||
"created": "Создан",
|
||
"view": "Открыть",
|
||
"noProjects": "Проекты ещё не настроены.",
|
||
"getStarted": "Нажмите «Добавить проект» для начала.",
|
||
"createProject": "Создать проект",
|
||
"creating": "Создание...",
|
||
"healthcheck": "Путь проверки здоровья",
|
||
"nameRequired": "Название и образ обязательны.",
|
||
"loadFailed": "Не удалось загрузить проекты",
|
||
"createFailed": "Не удалось создать проект",
|
||
"browseImages": "Обзор образов",
|
||
"selectImage": "Выберите образ",
|
||
"noImages": "Образы не найдены",
|
||
"loadingImages": "Загрузка образов...",
|
||
"imageLoadFailed": "Не удалось загрузить образы",
|
||
"alreadyAdded": "Уже добавлен",
|
||
"portHelpText": "Автоопределение из EXPOSE, если пусто",
|
||
"healthcheckHelpText": "Автоопределение из образа, если пусто",
|
||
"searchPlaceholder": "Поиск по имени, образу или реестру...",
|
||
"noMatchingProjects": "Проекты не найдены."
|
||
},
|
||
"projectDetail": {
|
||
"webhookTitle": "Webhook проекта",
|
||
"webhookDesc": "Отправьте POST с image-ссылкой на этот URL из CI — и Tinyforge запустит деплой. Стейдж выбирается по tag_pattern.",
|
||
"outgoingWebhookTitle": "Исходящий webhook (проект)",
|
||
"outgoingWebhookDesc": "Куда Tinyforge отправляет события деплоя для этого проекта. Стейджи могут переопределить; если нигде не задано — используется глобальная настройка.",
|
||
"outgoingFallbackGlobal": "глобальной настройки интеграций",
|
||
"notificationUrlLabel": "URL исходящего webhook",
|
||
"notificationUrlHelp": "Оставьте пустым для наследования из глобальных настроек. Стейджи могут переопределить.",
|
||
"stageNotificationUrlLabel": "URL исходящего webhook (этот стейдж)",
|
||
"stageNotificationUrlHelp": "Оставьте пустым для наследования от проекта, затем — из глобальных настроек.",
|
||
"stageOutgoingTitle": "Исходящий webhook (стейдж)",
|
||
"stageOutgoingDesc": "Куда Tinyforge отправляет события деплоя этого стейджа. Побеждает самый конкретный уровень.",
|
||
"stageFallbackLabel": "проектной или глобальной настройки",
|
||
"deleteProject": "Удалить проект",
|
||
"envVars": "Переменные окружения",
|
||
"volumes": "Тома",
|
||
"stages": "Стадии",
|
||
"noStages": "Для этого проекта не настроены стадии.",
|
||
"pattern": "Шаблон",
|
||
"autoDeploy": "авто-деплой",
|
||
"requiresConfirm": "нужно подтверждение",
|
||
"instances": "экземпляров",
|
||
"deployNewVersion": "Развернуть новую версию",
|
||
"selectTag": "Выберите тег для деплоя",
|
||
"loadingTags": "Загрузка тегов...",
|
||
"chooseTag": "Выберите тег...",
|
||
"enterTag": "Введите тег образа (напр., dev-abc123)",
|
||
"registryTag": "Реестр",
|
||
"localTag": "Локальный",
|
||
"alsoLocal": "Также доступен локально",
|
||
"searchTags": "Поиск тегов...",
|
||
"deployTag": "Тег",
|
||
"deploy": "Развернуть",
|
||
"deploying": "Развёртывание...",
|
||
"recentDeploys": "Последние деплои",
|
||
"noDeployHistory": "Нет истории деплоев для этого проекта.",
|
||
"tag": "Тег",
|
||
"status": "Статус",
|
||
"started": "Начат",
|
||
"finished": "Завершён",
|
||
"error": "Ошибка",
|
||
"noInstancesRunning": "Нет запущенных экземпляров",
|
||
"deleteConfirmTitle": "Удалить проект",
|
||
"deleteConfirmMessage": "Это безвозвратно удалит проект '{name}' и все его стадии, экземпляры и историю деплоев.",
|
||
"loadFailed": "Не удалось загрузить проект",
|
||
"deleteFailed": "Не удалось удалить проект",
|
||
"deployFailed": "Деплой не удался",
|
||
"nameLabel": "Название *",
|
||
"imageLabel": "Образ *",
|
||
"portLabel": "Порт",
|
||
"healthcheckLabel": "Путь проверки",
|
||
"saving": "Сохранение...",
|
||
"addStage": "Добавить стадию",
|
||
"tagPattern": "Шаблон тега",
|
||
"tagPatternHelp": "Glob-шаблон (напр., dev-*, v*)",
|
||
"maxInstances": "Макс. экземпляров",
|
||
"autoDeployLabel": "Авто-деплой",
|
||
"enableProxy": "Включить прокси",
|
||
"accessListId": "ID списка доступа NPM",
|
||
"accessListIdHelp": "Переопределить глобальный список доступа для этого проекта. Очистите, чтобы наследовать из настроек NPM.",
|
||
"localImages": "Локальные Docker-образы",
|
||
"imageTag": "Тег",
|
||
"imageId": "ID образа",
|
||
"imageSize": "Размер",
|
||
"imageCreated": "Создан",
|
||
"cpuLimit": "Лимит CPU (ядра)",
|
||
"cpuLimitHelp": "напр., 0.5, 1, 2. Оставьте 0 для без ограничений",
|
||
"memoryLimit": "Лимит памяти (МБ)",
|
||
"memoryLimitHelp": "напр., 256, 512, 1024. Оставьте 0 для без ограничений",
|
||
"npmProxy": "NPM прокси",
|
||
"creating": "Создание...",
|
||
"createStage": "Создать стадию",
|
||
"noProxy": "Без прокси",
|
||
"deleteStage": "Удалить стадию",
|
||
"deleteStageConfirm": "Удалить стадию \"{name}\"?",
|
||
"stageCreated": "Стадия \"{name}\" создана",
|
||
"stageUpdated": "Стадия обновлена",
|
||
"stageUpdateFailed": "Не удалось обновить стадию",
|
||
"stageDeleted": "Стадия \"{name}\" удалена",
|
||
"projectUpdated": "Проект обновлён",
|
||
"updateFailed": "Не удалось обновить проект",
|
||
"stageCreateFailed": "Не удалось создать стадию",
|
||
"stageDeleteFailed": "Не удалось удалить стадию"
|
||
},
|
||
"envEditor": {
|
||
"title": "Переменные окружения",
|
||
"description": "Управление переопределениями переменных окружения на уровне стадий. Значения стадий переопределяют значения проекта.",
|
||
"stage": "Стадия",
|
||
"projectDefaults": "Значения проекта по умолчанию",
|
||
"noProjectEnv": "Переменные окружения на уровне проекта ещё не определены.",
|
||
"stageOverrides": "Переопределения стадии",
|
||
"key": "Ключ",
|
||
"value": "Значение",
|
||
"secret": "Секрет",
|
||
"source": "Источник",
|
||
"actions": "Действия",
|
||
"overridden": "переопределено",
|
||
"inherited": "наследуется",
|
||
"overridesProject": "переопределяет проект",
|
||
"stageOnly": "только стадия",
|
||
"edit": "Изменить",
|
||
"change": "Изменить",
|
||
"delete": "Удалить",
|
||
"save": "Сохранить",
|
||
"add": "Добавить",
|
||
"adding": "Добавление...",
|
||
"noStages": "Стадии не настроены. Сначала добавьте стадии к проекту.",
|
||
"loadFailed": "Не удалось загрузить проект",
|
||
"envAdded": "Переменная окружения добавлена",
|
||
"envUpdated": "Переменная окружения обновлена",
|
||
"envDeleted": "Переменная окружения удалена",
|
||
"addFailed": "Не удалось добавить переменную",
|
||
"updateFailed": "Не удалось обновить переменную",
|
||
"deleteFailed": "Не удалось удалить переменную",
|
||
"loadEnvFailed": "Не удалось загрузить переменные",
|
||
"leaveEmptyToKeep": "Оставьте пустым, чтобы сохранить текущее",
|
||
"deleteTitle": "Удалить переменную окружения",
|
||
"deleteMessage": "Вы уверены, что хотите удалить эту переменную окружения? Это действие нельзя отменить."
|
||
},
|
||
"volumeEditor": {
|
||
"title": "Тома",
|
||
"description": "Настройка монтирования томов для контейнеров. Выберите область видимости для управления общим доступом между развёртываниями.",
|
||
"sourceHost": "Источник (хост)",
|
||
"targetContainer": "Цель (контейнер)",
|
||
"scope": "Область",
|
||
"nameColumn": "Имя",
|
||
"namePlaceholder": "напр. shared-db",
|
||
"requiresName": "требуется имя",
|
||
"noHostPath": "нет пути на хосте",
|
||
"tmpfs": "tmpfs (в памяти)",
|
||
"actions": "Действия",
|
||
"edit": "Изменить",
|
||
"delete": "Удалить",
|
||
"save": "Сохранить",
|
||
"add": "Добавить",
|
||
"adding": "Добавление...",
|
||
"scopeGuide": "Области видимости томов",
|
||
"noVolumes": "Тома ещё не настроены. Добавьте один выше.",
|
||
"volumeAdded": "Том добавлен",
|
||
"volumeUpdated": "Том обновлён",
|
||
"volumeDeleted": "Том удалён",
|
||
"loadFailed": "Не удалось загрузить тома",
|
||
"addFailed": "Не удалось добавить том",
|
||
"updateFailed": "Не удалось обновить том",
|
||
"deleteFailed": "Не удалось удалить том"
|
||
},
|
||
"volumeBrowser": {
|
||
"title": "Обзор тома",
|
||
"loadFailed": "Не удалось загрузить каталог",
|
||
"empty": "Этот каталог пуст.",
|
||
"name": "Имя",
|
||
"size": "Размер",
|
||
"modified": "Изменён",
|
||
"downloadAll": "Скачать том как ZIP",
|
||
"downloadFolder": "Скачать папку как ZIP",
|
||
"upload": "Загрузить файлы",
|
||
"uploaded": "Загружено",
|
||
"files": "файл(ов)",
|
||
"uploadFailed": "Не удалось загрузить файлы",
|
||
"browse": "Обзор",
|
||
"download": "Скачать"
|
||
},
|
||
"quickDeploy": {
|
||
"title": "Быстрый деплой",
|
||
"description": "Разверните образ контейнера без настройки. Вставьте URL образа, проверьте параметры и разверните.",
|
||
"step1": "1. Введите URL образа",
|
||
"imageUrl": "URL образа",
|
||
"imageUrlHelp": "Полный URL образа с тегом (напр., git.example.com/user/app:dev-abc123)",
|
||
"inspect": "Проверить",
|
||
"inspecting": "Проверка...",
|
||
"step2": "2. Проверка конфигурации",
|
||
"reviewDesc": "Эти параметры были обнаружены из образа. Измените при необходимости перед деплоем.",
|
||
"projectName": "Имя проекта",
|
||
"port": "Порт",
|
||
"portHelp": "Порт контейнера (1-65535)",
|
||
"healthCheckPath": "Путь проверки здоровья",
|
||
"healthCheckHelp": "Необязательный HTTP-путь для проверки работоспособности",
|
||
"stage": "Стадия",
|
||
"development": "Разработка",
|
||
"release": "Релиз",
|
||
"production": "Продакшн",
|
||
"stageHelp": "Стадия развёртывания для этого образа",
|
||
"subdomainOverride": "Переопределение поддомена",
|
||
"subdomainHelp": "Оставьте пустым для использования шаблона по умолчанию",
|
||
"envVars": "Переменные окружения",
|
||
"envVarsHelp": "По одной на строку, формат KEY=VALUE",
|
||
"step3": "3. Развёртывание",
|
||
"deployDesc": "Будет создан новый проект и контейнер будет развёрнут немедленно.",
|
||
"deployBtn": "Развернуть",
|
||
"inspectedSuccess": "Образ успешно проверен",
|
||
"deployedSuccess": "{name} успешно развёрнут!",
|
||
"inspectFailed": "Не удалось проверить образ",
|
||
"deployFailed": "Развёртывание не удалось",
|
||
"browseImages": "Обзор",
|
||
"selectImage": "Выберите образ из реестра",
|
||
"noImages": "Образы не найдены",
|
||
"loadingImages": "Загрузка...",
|
||
"imageLoadFailed": "Не удалось загрузить образы",
|
||
"autoDeployLabel": "Развернуть сразу",
|
||
"lowercaseHint": "Строчные буквы и дефисы",
|
||
"imageAlreadyExists": "Образ уже развёрнут",
|
||
"conflictDescription": "Проект с этим образом уже существует. Откройте существующий проект для развёртывания новой версии или создайте отдельный проект.",
|
||
"openProject": "Открыть проект \u2192",
|
||
"createNewAnyway": "Создать новый проект"
|
||
},
|
||
"settings": {
|
||
"title": "Настройки",
|
||
"general": "Общие",
|
||
"integrations": "Интеграции",
|
||
"dns": "DNS",
|
||
"maintenance": "Обслуживание",
|
||
"registries": "Реестры",
|
||
"credentials": "Учётные данные",
|
||
"authentication": "Аутентификация",
|
||
"backup": "Резервные копии",
|
||
"appearance": "Внешний вид",
|
||
"groupMain": "Обзор",
|
||
"groupProxy": "Маршрутизация",
|
||
"groupSystem": "Система",
|
||
"groupSecurity": "Безопасность",
|
||
"staleThreshold": "Порог устаревания (дни)",
|
||
"staleThresholdHelp": "Контейнеры, неактивные дольше этого срока, будут помечены как устаревшие.",
|
||
"dockerCleanup": "Очистка Docker-образов",
|
||
"dockerCleanupHelp": "Удаление неиспользуемых Docker-образов ваших проектов. Удаляются только образы, не используемые активными экземплярами.",
|
||
"pruneThreshold": "Порог предупреждения (МБ)",
|
||
"pruneThresholdHelp": "Показывать предупреждение на дашборде, когда неиспользуемые образы превышают этот размер. 0 = отключено.",
|
||
"pruneImages": "Очистить неиспользуемые образы",
|
||
"pruning": "Очистка...",
|
||
"pruneResult": "Удалено {count} образов, освобождено {mb} МБ",
|
||
"pruneConfirmMessage": "Будут удалены неиспользуемые Docker-образы ваших проектов. Образы активных экземпляров не затрагиваются.",
|
||
"pruneFailed": "Не удалось очистить образы",
|
||
"proxyProvider": "Провайдер прокси",
|
||
"proxyProviderHelp": "Выберите способ управления обратным прокси для развёрнутых контейнеров.",
|
||
"proxyNone": "Нет",
|
||
"proxyNoneDesc": "Без прокси — контейнеры доступны напрямую по порту",
|
||
"proxyNpm": "Nginx Proxy Manager",
|
||
"proxyNpmDesc": "Маршруты через NPM API (настройте учётные данные ниже)",
|
||
"npm": "Nginx Proxy Manager",
|
||
"traefik": "Traefik",
|
||
"traefikLabelsTitle": "Справка по Docker-меткам",
|
||
"traefikLabelsDesc": "Эти метки автоматически добавляются к развёрнутым контейнерам. Показаны для справки.",
|
||
"proxyTraefik": "Traefik",
|
||
"proxyTraefikDesc": "Автообнаружение через Docker-метки — без API-вызовов",
|
||
"proxyNoneWarning": "Переключение на «Нет» не удаляет существующие прокси-маршруты. Возможно, потребуется очистить их вручную.",
|
||
"traefikEntrypoint": "Точка входа",
|
||
"traefikEntrypointHelp": "Имя точки входа Traefik для HTTPS-маршрутов",
|
||
"traefikCertResolver": "Резолвер сертификатов",
|
||
"traefikCertResolverHelp": "Имя резолвера TLS-сертификатов (напр., letsencrypt)",
|
||
"traefikNetwork": "Docker-сеть",
|
||
"traefikNetworkHelp": "Сеть, которую слушает Traefik (оставьте пустым для глобальной сети)",
|
||
"traefikApiUrl": "URL API Traefik",
|
||
"traefikApiUrlHelp": "Необязательно — для проверки состояния (напр., http://traefik:8080)"
|
||
},
|
||
"settingsGeneral": {
|
||
"title": "Общие настройки",
|
||
"globalConfig": "Глобальная конфигурация",
|
||
"globalConfigDesc": "Базовая инфраструктура: домен, сеть и интервал опроса, используемые Tinyforge для оркестрации контейнеров.",
|
||
"configureNpm": "Выбран Nginx Proxy Manager.",
|
||
"configureTraefik": "Выбран Traefik.",
|
||
"configureLink": "Настроить провайдера",
|
||
"domain": "Домен",
|
||
"domainHelp": "Базовый домен для маршрутизации (напр., example.com → stage-dev-app.example.com)",
|
||
"serverIp": "IP сервера (Docker Host)",
|
||
"serverIpHelp": "IP машины с Docker. Используется для удалённого NPM.",
|
||
"publicIp": "Публичный IP (для DNS)",
|
||
"publicIpHelp": "IP для DNS A-записей — обычно адрес прокси/балансировщика. Если пусто, используется IP сервера.",
|
||
"dockerNetwork": "Docker-сеть",
|
||
"dockerNetworkHelp": "Docker-сеть, общая для контейнеров и прокси. Должна совпадать с сетью NPM/Traefik.",
|
||
"subdomainPattern": "Шаблон поддомена",
|
||
"subdomainPatternHelp": "Шаблон для автоматически генерируемых поддоменов",
|
||
"subdomainVarsTitle": "Доступные переменные",
|
||
"varProject": "Имя проекта",
|
||
"varStage": "Имя стадии",
|
||
"varTag": "Тег образа",
|
||
"varPort": "Порт контейнера",
|
||
"pollingInterval": "Интервал опроса (секунды)",
|
||
"pollingIntervalHelp": "Как часто проверять реестры на новые теги (60-86400)",
|
||
"notificationUrl": "URL уведомлений",
|
||
"notificationUrlHelp": "URL вебхука для уведомлений о деплоях",
|
||
"saveSettings": "Сохранить настройки",
|
||
"saving": "Сохранение...",
|
||
"saved": "Настройки успешно сохранены",
|
||
"saveFailed": "Не удалось сохранить настройки",
|
||
"loadFailed": "Не удалось загрузить настройки",
|
||
"webhookUrl": "URL вебхука",
|
||
"webhookDesc": "Этот секретный URL получает уведомления о push-событиях из вашего CI-пайплайна.",
|
||
"noWebhookUrl": "URL вебхука не настроен",
|
||
"copy": "Копировать",
|
||
"copied": "URL вебхука скопирован в буфер обмена",
|
||
"regenerateUrl": "Перегенерировать URL",
|
||
"regenerating": "Перегенерация...",
|
||
"regenerated": "URL вебхука перегенерирован",
|
||
"regenerateFailed": "Не удалось перегенерировать URL вебхука",
|
||
"regenerateWarning": "Внимание: перегенерация сделает текущий URL недействительным. Обновите ваши CI-пайплайны.",
|
||
"sslCertificate": "SSL-сертификат",
|
||
"sslCertificateHelp": "Wildcard-сертификат из NPM для автоматического SSL на прокси-хостах",
|
||
"selectCertificate": "Выбрать сертификат",
|
||
"noCertificate": "Нет (без SSL)",
|
||
"clearCertificate": "Очистить",
|
||
"loadingCertificates": "Загрузка сертификатов...",
|
||
"noCertificatesFound": "Wildcard-сертификаты в NPM не найдены",
|
||
"dnsConfig": "Настройки DNS",
|
||
"wildcardDns": "Wildcard DNS настроен",
|
||
"wildcardDnsHelp": "Когда включено, все поддомены разрешаются на ваш сервер через wildcard DNS правило. Отключите для управления DNS-записями для каждого сервиса.",
|
||
"dnsProvider": "DNS-провайдер",
|
||
"dnsProviderHelp": "Выберите DNS-провайдера для автоматического управления записями",
|
||
"cloudflareApiToken": "API-токен Cloudflare",
|
||
"cloudflareApiTokenHelp": "API-токен с правами редактирования DNS для вашей зоны",
|
||
"cloudflareApiTokenPlaceholder": "Введите API-токен Cloudflare",
|
||
"cloudflareApiTokenConfigured": "API-токен настроен",
|
||
"cloudflareZone": "Зона Cloudflare",
|
||
"cloudflareZoneHelp": "Выберите DNS-зону для управления записями",
|
||
"selectZone": "Выбрать зону",
|
||
"noZone": "Зона не выбрана",
|
||
"loadingZones": "Загрузка зон...",
|
||
"noZonesFound": "Зоны для этого токена не найдены",
|
||
"testConnection": "Проверить соединение",
|
||
"testingConnection": "Проверка...",
|
||
"connectionSuccess": "Соединение успешно",
|
||
"connectionFailed": "Ошибка соединения",
|
||
"baseVolumePath": "Базовый путь томов",
|
||
"baseVolumePathHelp": "Добавляется к относительным путям источников (напр., /data + my-app/uploads = /data/my-app/uploads)"
|
||
},
|
||
"settingsRegistries": {
|
||
"title": "Реестры контейнеров",
|
||
"description": "Управление реестрами контейнеров для обнаружения образов.",
|
||
"addRegistry": "Добавить реестр",
|
||
"editRegistry": "Редактировать реестр",
|
||
"addNewRegistry": "Добавить новый реестр",
|
||
"name": "Название",
|
||
"nameHelp": "Понятное название для этого реестра",
|
||
"url": "URL",
|
||
"urlHelp": "Базовый URL реестра",
|
||
"type": "Тип",
|
||
"typeHelp": "Тип реестра для совместимости API",
|
||
"token": "Токен",
|
||
"tokenHelpNew": "API-токен для аутентификации",
|
||
"tokenHelpEdit": "Оставьте пустым, чтобы сохранить текущий токен",
|
||
"owner": "Владелец",
|
||
"ownerHelp": "Владельцы пакетов через запятую (напр., alexei,my-org)",
|
||
"save": "Сохранить",
|
||
"saving": "Сохранение...",
|
||
"update": "Обновить",
|
||
"test": "Тест",
|
||
"testing": "Тестирование...",
|
||
"edit": "Изменить",
|
||
"delete": "Удалить",
|
||
"noRegistries": "Реестры ещё не настроены.",
|
||
"addFirst": "Добавьте первый реестр",
|
||
"registryUpdated": "Реестр обновлён",
|
||
"registryAdded": "Реестр добавлен",
|
||
"registryDeleted": "Реестр «{name}» удалён",
|
||
"testSuccess": "Подключение к «{name}» успешно",
|
||
"saveFailed": "Не удалось сохранить реестр",
|
||
"deleteFailed": "Не удалось удалить реестр",
|
||
"testFailed": "Тест подключения не удался",
|
||
"loadFailed": "Не удалось загрузить реестры",
|
||
"deleteConfirm": "Удалить реестр «{name}»? Это действие необратимо.",
|
||
"healthChecking": "Проверка...",
|
||
"healthConnected": "Подключено",
|
||
"healthUnreachable": "Недоступно"
|
||
},
|
||
"settingsNpm": {
|
||
"testConnection": "Проверить соединение",
|
||
"testing": "Проверка...",
|
||
"testSuccess": "Подключение к NPM успешно",
|
||
"testFailed": "Не удалось подключиться к NPM",
|
||
"saveFailedConnection": "Невозможно сохранить — проверка соединения не пройдена",
|
||
"remoteMode": "Удалённый NPM",
|
||
"remoteModeHelp": "Включите, если NPM работает на другой машине. Перенаправление на IP сервера с опубликованными портами.",
|
||
"remoteModeWarning": "Требуется IP сервера в общих настройках. Порты автоматически привязываются к случайным портам хоста.",
|
||
"accessList": "Список доступа по умолчанию",
|
||
"accessListHelp": "Список доступа NPM для HTTP-аутентификации на прокси-хостах. Можно переопределить для каждого проекта.",
|
||
"noAccessList": "Глобальные настройки",
|
||
"selectAccessList": "Выберите список доступа",
|
||
"noAccessLists": "Списки доступа в NPM не найдены",
|
||
"accessListLoadFailed": "Не удалось загрузить списки доступа"
|
||
},
|
||
"settingsCredentials": {
|
||
"title": "Учётные данные",
|
||
"description": "Управление учётными данными для Nginx Proxy Manager и токенами реестров. Все значения зашифрованы.",
|
||
"npm": "Nginx Proxy Manager",
|
||
"npmDesc": "Учётные данные для управления прокси-хостами через NPM API",
|
||
"configured": "Настроено",
|
||
"npmUrl": "URL NPM",
|
||
"npmUrlHelp": "URL API Nginx Proxy Manager",
|
||
"email": "Email",
|
||
"emailHelp": "Email администратора NPM",
|
||
"password": "Пароль",
|
||
"passwordHelpNew": "Пароль администратора NPM (будет зашифрован)",
|
||
"passwordHelpEdit": "Введите новый пароль для замены текущего",
|
||
"changeCredentials": "Изменить учётные данные",
|
||
"save": "Сохранить",
|
||
"saving": "Сохранение...",
|
||
"saved": "Учётные данные NPM сохранены",
|
||
"saveFailed": "Не удалось сохранить учётные данные NPM",
|
||
"loadFailed": "Не удалось загрузить учётные данные",
|
||
"registryTokens": "Токены реестров",
|
||
"registryTokensDesc": "Токены аутентификации реестров управляются для каждого реестра в разделе",
|
||
"registriesLink": "Реестры",
|
||
"registryTokensSuffix": ". Каждый реестр хранит свой токен в зашифрованном виде.",
|
||
"notSet": "Не задано"
|
||
},
|
||
"settingsBackup": {
|
||
"title": "Управление резервными копиями",
|
||
"description": "Управление резервными копиями базы данных и настройка автоматического резервного копирования.",
|
||
"autoBackup": "Автоматическое резервное копирование",
|
||
"autoBackupHelp": "Автоматически создавать резервные копии с заданным интервалом.",
|
||
"interval": "Интервал копирования",
|
||
"intervalHelp": "Как часто создавать автоматические резервные копии.",
|
||
"intervalHours": "{hours} часов",
|
||
"retention": "Количество хранимых копий",
|
||
"retentionHelp": "Максимальное количество хранимых резервных копий. Старые удаляются первыми.",
|
||
"backupNow": "Создать копию",
|
||
"creatingBackup": "Создание...",
|
||
"backupCreated": "Резервная копия создана",
|
||
"backupFailed": "Не удалось создать резервную копию",
|
||
"backupList": "Резервные копии",
|
||
"noBackups": "Резервных копий пока нет. Создайте вручную или включите автоматическое копирование.",
|
||
"columnFilename": "Файл",
|
||
"columnSize": "Размер",
|
||
"columnType": "Тип",
|
||
"columnDate": "Создано",
|
||
"columnActions": "Действия",
|
||
"download": "Скачать",
|
||
"delete": "Удалить",
|
||
"restore": "Восстановить",
|
||
"deleteConfirm": "Вы уверены, что хотите удалить эту резервную копию?",
|
||
"deleted": "Резервная копия удалена",
|
||
"deleteFailed": "Не удалось удалить резервную копию",
|
||
"restoreConfirm": "Вы уверены, что хотите восстановить из этой копии? Текущая база данных будет заменена и сервер будет перезапущен. Все текущие данные будут потеряны.",
|
||
"restoreWarning": "Это действие необратимо!",
|
||
"restored": "База данных восстановлена. Сервер перезапускается...",
|
||
"restoreFailed": "Не удалось восстановить резервную копию",
|
||
"typeManual": "Ручная",
|
||
"typeAuto": "Авто",
|
||
"typePreDeploy": "Перед деплоем",
|
||
"preDeploy": "Снимок перед каждым деплоем",
|
||
"preDeployHelp": "Создавать снимок БД Tinyforge в начале каждого деплоя проекта. Независимо от периодического расписания выше; восстанавливается из списка ниже по типу «Перед деплоем».",
|
||
"save": "Сохранить",
|
||
"saving": "Сохранение...",
|
||
"saved": "Настройки копирования сохранены",
|
||
"saveFailed": "Не удалось сохранить настройки копирования"
|
||
},
|
||
"settingsAuth": {
|
||
"title": "Настройки аутентификации",
|
||
"description": "Настройка режима аутентификации и управление пользователями.",
|
||
"authMode": "Режим аутентификации",
|
||
"local": "Локальный (логин/пароль)",
|
||
"oidc": "OIDC (SSO)",
|
||
"oidcConfig": "Конфигурация OIDC-провайдера",
|
||
"issuerUrl": "URL издателя",
|
||
"clientId": "ID клиента",
|
||
"clientSecret": "Секрет клиента",
|
||
"redirectUrl": "URL перенаправления",
|
||
"saveSettings": "Сохранить настройки",
|
||
"saving": "Сохранение...",
|
||
"saved": "Настройки сохранены",
|
||
"saveFailed": "Не удалось сохранить",
|
||
"loadFailed": "Не удалось загрузить настройки",
|
||
"localUsers": "Локальные пользователи",
|
||
"username": "Имя пользователя",
|
||
"email": "Email",
|
||
"role": "Роль",
|
||
"created": "Создан",
|
||
"noUsers": "Пользователи не найдены.",
|
||
"addUser": "Добавить пользователя",
|
||
"viewer": "Наблюдатель",
|
||
"admin": "Администратор",
|
||
"userCreated": "Пользователь создан",
|
||
"userDeleted": "Пользователь удалён",
|
||
"createFailed": "Не удалось создать пользователя",
|
||
"deleteFailed": "Не удалось удалить пользователя",
|
||
"deleteConfirm": "Вы уверены, что хотите удалить этого пользователя?",
|
||
"usernameRequired": "Имя пользователя и пароль обязательны",
|
||
"networkError": "Ошибка сети",
|
||
"password": "Пароль"
|
||
},
|
||
"login": {
|
||
"title": "Tinyforge",
|
||
"subtitle": "Войдите в свой аккаунт",
|
||
"username": "Имя пользователя",
|
||
"password": "Пароль",
|
||
"signIn": "Войти",
|
||
"signingIn": "Вход...",
|
||
"or": "или",
|
||
"ssoButton": "Войти через SSO (OIDC)",
|
||
"loginFailed": "Ошибка входа",
|
||
"networkError": "Ошибка сети"
|
||
},
|
||
"proxies": {
|
||
"title": "Менеджер прокси",
|
||
"create": "Создать прокси",
|
||
"standalone": "Автономные прокси",
|
||
"managed": "Управляемые прокси",
|
||
"noProxies": "Прокси не найдены",
|
||
"noProxiesDesc": "Создайте автономный прокси или разверните проект с включённым прокси.",
|
||
"filter": {
|
||
"search": "Поиск по домену или назначению...",
|
||
"health": "Здоровье",
|
||
"type": "Тип",
|
||
"all": "Все",
|
||
"clear": "Сбросить фильтры"
|
||
},
|
||
"health": {
|
||
"healthy": "Здоров",
|
||
"unhealthy": "Нездоров",
|
||
"unknown": "Неизвестно"
|
||
},
|
||
"lastChecked": "Последняя проверка"
|
||
},
|
||
"sites": {
|
||
"webhookTitle": "Webhook сайта",
|
||
"webhookDesc": "Укажите этот URL в push-вебхуке Git-провайдера. Tinyforge пересинхронизирует сайт при подходящей ref-ссылке (ветка для push, шаблон тега для tag). Пустое тело запускает синхронизацию безусловно.",
|
||
"outgoingUrlTitle": "URL исходящего webhook (этот сайт)",
|
||
"outgoingUrlDesc": "Куда Tinyforge отправляет события site_sync_success / site_sync_failure. Пусто — наследовать из глобальных настроек.",
|
||
"outgoingWebhookTitle": "Исходящий webhook (сайт)",
|
||
"outgoingWebhookDesc": "HMAC-секрет и тестовая отправка для разрешённого исходящего URL.",
|
||
"outgoingFallbackGlobal": "глобальной настройки интеграций",
|
||
"title": "Статические сайты",
|
||
"addSite": "Новый сайт",
|
||
"newSite": "Новый статический сайт",
|
||
"createSite": "Создать сайт",
|
||
"noSites": "Нет статических сайтов",
|
||
"noSitesDesc": "Разверните статический контент из папки Git-репозитория.",
|
||
"searchPlaceholder": "Поиск по имени, домену или репозиторию...",
|
||
"noMatching": "Нет сайтов, соответствующих поиску.",
|
||
"name": "Имя",
|
||
"domain": "Домен",
|
||
"mode": "Режим",
|
||
"status": "Статус",
|
||
"lastSync": "Последняя синхр.",
|
||
"deploy": "Развернуть",
|
||
"stop": "Остановить",
|
||
"start": "Запустить",
|
||
"openSite": "Открыть сайт",
|
||
"confirmDelete": "Удалить сайт",
|
||
"confirmDeleteMsg": "Это удалит сайт и его контейнер",
|
||
"confirmDeleteSecret": "Удалить секрет",
|
||
"confirmDeleteSecretMsg": "Вы уверены, что хотите удалить секрет",
|
||
"siteInfo": "Информация о сайте",
|
||
"folder": "Папка",
|
||
"syncTrigger": "Триггер синхр.",
|
||
"commitSha": "Коммит SHA",
|
||
"secrets": "Секреты",
|
||
"addSecret": "Добавить секрет",
|
||
"noSecrets": "Секреты не настроены. Добавьте их, если сайту нужны серверные API-ключи.",
|
||
"secretKey": "Ключ",
|
||
"secretValue": "Значение",
|
||
"encryptSecret": "Шифровать значение",
|
||
"saveSecret": "Добавить секрет",
|
||
"step1Title": "1. Репозиторий",
|
||
"step2Title": "2. Выбор ветки",
|
||
"step3Title": "3. Выбор папки",
|
||
"step4Title": "4. Настройки",
|
||
"step5Title": "5. Проверка и создание",
|
||
"fullRepoUrl": "URL репозитория",
|
||
"fullRepoUrlHelp": "Вставьте полный URL для автозаполнения полей ниже (напр., https://git.example.com/owner/repo)",
|
||
"serverUrl": "URL сервера",
|
||
"repoUrl": "URL Git-сервера",
|
||
"repoUrlHelp": "Вставьте полный URL репозитория или базовый URL сервера (Gitea, Forgejo, Gogs)",
|
||
"repoOwner": "Владелец",
|
||
"repoName": "Репозиторий",
|
||
"accessToken": "Токен доступа",
|
||
"accessTokenPlaceholder": "Необязательно — для приватных репозиториев",
|
||
"accessTokenHelp": "Персональный токен с правами на чтение репозитория. Оставьте пустым для публичных.",
|
||
"noToken": "Нет (публичный репо)",
|
||
"testConnection": "Проверить соединение",
|
||
"connectionSuccess": "Репозиторий доступен",
|
||
"loadingBranches": "Загрузка веток...",
|
||
"selectBranch": "Выберите ветку",
|
||
"chooseBranch": "Выберите ветку...",
|
||
"branch": "Ветка",
|
||
"loadingTree": "Загрузка дерева репозитория...",
|
||
"selectFolder": "Выберите папку с файлами сайта",
|
||
"selectedFolder": "Выбранная папка",
|
||
"siteName": "Имя сайта",
|
||
"domainHelp": "Публичный домен сайта. Прокси будет настроен автоматически.",
|
||
"modeStaticDesc": "HTML, CSS, JS, изображения через Nginx",
|
||
"modeDenoDesc": "Статические файлы + серверный API из папки api/",
|
||
"triggerManual": "Вручную",
|
||
"triggerPush": "При пуше",
|
||
"triggerTag": "По тегу",
|
||
"tagPattern": "Паттерн тега",
|
||
"tagPatternHelp": "Glob-паттерн для тегов (напр., v*, pages-*)",
|
||
"renderMarkdown": "Рендерить Markdown-файлы в HTML",
|
||
"provider": "Git-провайдер",
|
||
"detectedProvider": "Автоопределён",
|
||
"browseRepos": "Обзор репозиториев",
|
||
"selectRepo": "Выберите репозиторий",
|
||
"storage": "Хранилище данных",
|
||
"enableStorage": "Включить хранилище данных",
|
||
"storageHelp": "Подключает Docker-том в /app/data, чтобы Deno-бэкенд мог читать и записывать файлы, сохраняющиеся между деплоями.",
|
||
"storageLimitMB": "Лимит хранилища (МБ)",
|
||
"storageLimitHelp": "Максимальный размер хранилища в мегабайтах. 0 = без ограничений.",
|
||
"storageVolume": "Том",
|
||
"dataPath": "Путь к данным",
|
||
"storageMountPath": "Путь монтирования",
|
||
"storageLimit": "Лимит",
|
||
"storageUsed": "Использовано",
|
||
"storageOfLimit": "от лимита использовано",
|
||
"unlimited": "Без ограничений"
|
||
},
|
||
"common": {
|
||
"cancel": "Отмена",
|
||
"confirm": "Подтвердить",
|
||
"delete": "Удалить",
|
||
"edit": "Изменить",
|
||
"change": "Изменить",
|
||
"save": "Сохранить",
|
||
"retry": "Повторить",
|
||
"loading": "Загрузка...",
|
||
"noData": "Нет данных",
|
||
"project": "Проект",
|
||
"back": "Назад",
|
||
"actions": "Действия",
|
||
"stop": "Остановить",
|
||
"start": "Запустить",
|
||
"restart": "Перезапустить",
|
||
"remove": "Удалить",
|
||
"instance": "экземпляр",
|
||
"instances": "экземпляров",
|
||
"next": "Далее",
|
||
"yes": "Да",
|
||
"no": "Нет",
|
||
"saving": "Сохранение..."
|
||
},
|
||
"instance": {
|
||
"stopConfirm": "Контейнер будет остановлен. Экземпляр можно будет запустить снова позже.",
|
||
"restartConfirm": "Контейнер будет перезапущен с кратковременным простоем.",
|
||
"removeConfirm": "Контейнер и его прокси-конфигурация будут безвозвратно удалены.",
|
||
"actionFailed": "Действие не удалось"
|
||
},
|
||
"empty": {
|
||
"noProjects": "Проектов пока нет",
|
||
"noProjectsDesc": "Начните с создания первого проекта или используйте быстрый деплой.",
|
||
"createProject": "Создать проект",
|
||
"noInstances": "Нет экземпляров",
|
||
"noInstancesDesc": "Разверните новую версию, чтобы увидеть экземпляры здесь.",
|
||
"noDeploys": "Нет истории деплоев",
|
||
"noDeploysDesc": "История деплоев появится здесь после первого развёртывания.",
|
||
"noRegistries": "Нет реестров",
|
||
"noRegistriesDesc": "Добавьте реестр контейнеров для обнаружения образов.",
|
||
"noVolumes": "Нет томов",
|
||
"noVolumesDesc": "Настройте монтирование томов для постоянных данных.",
|
||
"noUsers": "Нет пользователей",
|
||
"noUsersDesc": "Добавьте локальных пользователей для управления доступом."
|
||
},
|
||
"validation": {
|
||
"required": "Поле {field} обязательно",
|
||
"invalidUrl": "Неверный формат URL",
|
||
"invalidDomain": "Неверный формат домена",
|
||
"invalidIp": "Неверный формат IP",
|
||
"invalidEmail": "Неверный формат email",
|
||
"invalidPort": "Порт должен быть от 1 до 65535",
|
||
"invalidPollingInterval": "Интервал опроса должен быть от 60 до 86400 секунд",
|
||
"invalidProjectName": "Допускаются только строчные буквы, цифры и дефисы",
|
||
"requiredWhenUpdating": "Поле {field} обязательно при обновлении учётных данных",
|
||
"requiredForNew": "Поле {field} обязательно для новых реестров"
|
||
},
|
||
"confirm": {
|
||
"stopInstance": "Остановить экземпляр",
|
||
"startInstance": "Запустить экземпляр",
|
||
"restartInstance": "Перезапустить экземпляр",
|
||
"removeInstance": "Удалить экземпляр",
|
||
"stopAction": "Остановить",
|
||
"restartAction": "Перезапустить",
|
||
"removeAction": "Удалить"
|
||
},
|
||
"theme": {
|
||
"light": "Светлая",
|
||
"dark": "Тёмная",
|
||
"system": "Системная"
|
||
},
|
||
"entityPicker": {
|
||
"search": "Поиск...",
|
||
"noResults": "Ничего не найдено"
|
||
},
|
||
"stale": {
|
||
"title": "Устаревшие контейнеры",
|
||
"noStale": "Нет устаревших контейнеров",
|
||
"noStaleDesc": "Все контейнеры исправны и работают.",
|
||
"cleanup": "Очистить",
|
||
"cleanupAll": "Очистить все",
|
||
"confirmCleanup": "Это остановит и удалит контейнер. Продолжить?",
|
||
"confirmBulkCleanup": "Это остановит и удалит все устаревшие контейнеры. Продолжить?",
|
||
"daysStale": "дней устарел",
|
||
"lastAlive": "Последний раз жив",
|
||
"count": "Устаревшие",
|
||
"cleanedUp": "Контейнер очищен",
|
||
"bulkCleanedUp": "{count} контейнеров очищено",
|
||
"cleanupFailed": "Не удалось очистить",
|
||
"loadFailed": "Не удалось загрузить устаревшие контейнеры"
|
||
},
|
||
"proxies": {
|
||
"title": "Прокси",
|
||
"create": "Создать прокси",
|
||
"noProxies": "Прокси ещё не настроены.",
|
||
"noProxiesDesc": "Создайте автономный прокси или разверните проект, чтобы увидеть прокси здесь.",
|
||
"standalone": "Автономные прокси",
|
||
"managed": "Управляемые",
|
||
"lastChecked": "Последняя проверка",
|
||
"health": {
|
||
"healthy": "Работает",
|
||
"unhealthy": "Недоступен",
|
||
"unknown": "Неизвестно"
|
||
},
|
||
"filter": {
|
||
"search": "Поиск прокси...",
|
||
"health": "Здоровье",
|
||
"type": "Тип",
|
||
"all": "Все",
|
||
"clear": "Сбросить фильтры"
|
||
},
|
||
"form": {
|
||
"title": "Создать прокси",
|
||
"editTitle": "Редактировать прокси",
|
||
"destination": "URL / IP назначения",
|
||
"port": "Порт",
|
||
"domain": "Домен",
|
||
"domainHelp": "Публичный домен для этого прокси.",
|
||
"validate": "Проверить",
|
||
"validating": "Проверка...",
|
||
"create": "Создать прокси",
|
||
"save": "Сохранить изменения",
|
||
"cancel": "Отмена",
|
||
"delete": "Удалить",
|
||
"deleteConfirm": "Удалить этот прокси? Это действие необратимо."
|
||
},
|
||
"validation": {
|
||
"title": "Проверка назначения",
|
||
"syntax": "Синтаксис URL",
|
||
"dns": "DNS разрешение",
|
||
"tcp": "TCP подключение",
|
||
"http": "HTTP ответ",
|
||
"checking": "Проверка...",
|
||
"skipped": "Пропущено"
|
||
}
|
||
},
|
||
"proxies": {
|
||
"title": "Прокси-маршруты",
|
||
"description": "Активные прокси-маршруты от контейнеров и статических сайтов.",
|
||
"domain": "Домен",
|
||
"project": "Проект / Сайт",
|
||
"stage": "Этап / Режим",
|
||
"tag": "Тег",
|
||
"port": "Порт",
|
||
"status": "Статус",
|
||
"source": "Источник",
|
||
"sourceContainer": "Контейнер",
|
||
"sourceStatic": "Статический сайт",
|
||
"sourceDeno": "Deno-сайт",
|
||
"filterAll": "Все",
|
||
"filterContainers": "Контейнеры",
|
||
"filterSites": "Сайты",
|
||
"noRoutes": "Нет прокси-маршрутов",
|
||
"noRoutesDesc": "Прокси-маршруты создаются автоматически при развёртывании контейнера с прокси или публикации статического сайта.",
|
||
"searchPlaceholder": "Поиск по домену, проекту или тегу...",
|
||
"noMatch": "Нет маршрутов, соответствующих поиску.",
|
||
"loadFailed": "Не удалось загрузить прокси-маршруты",
|
||
"route": "маршрут",
|
||
"routes": "маршрутов"
|
||
},
|
||
"logs": {
|
||
"title": "Логи контейнера",
|
||
"lines": "строк",
|
||
"follow": "Следить",
|
||
"following": "Слежение...",
|
||
"loading": "Загрузка логов...",
|
||
"noLogs": "Нет вывода логов"
|
||
},
|
||
"events": {
|
||
"title": "Журнал событий",
|
||
"noEvents": "Событий не найдено",
|
||
"noEventsDesc": "События будут отображаться здесь по мере их возникновения.",
|
||
"loadMore": "Загрузить ещё",
|
||
"newEvents": "новых событий",
|
||
"totalCount": "всего {count}",
|
||
"clearAll": "Очистить всё",
|
||
"clearAllTitle": "Очистить журнал событий",
|
||
"clearAllMessage": "Все записи журнала событий будут удалены безвозвратно.",
|
||
"cleared": "Удалено {count} событий",
|
||
"clearFailed": "Не удалось очистить события",
|
||
"filter": {
|
||
"severity": "Уровень",
|
||
"source": "Источник",
|
||
"dateRange": "Период",
|
||
"search": "Поиск событий...",
|
||
"lastHour": "Последний час",
|
||
"last24h": "Последние 24 часа",
|
||
"last7d": "Последние 7 дней",
|
||
"allTime": "За всё время",
|
||
"clear": "Сбросить фильтры"
|
||
},
|
||
"severity": {
|
||
"info": "Инфо",
|
||
"warn": "Предупреждение",
|
||
"error": "Ошибка"
|
||
},
|
||
"source": {
|
||
"deploy": "Развёртывание",
|
||
"static_site": "Статический сайт",
|
||
"stale_scanner": "Сканер устаревших",
|
||
"stale_cleanup": "Очистка устаревших",
|
||
"admin": "Администратор"
|
||
},
|
||
"metadata": "Подробности"
|
||
},
|
||
"stats": {
|
||
"cpu": "ЦП",
|
||
"mem": "ОЗУ",
|
||
"unavailable": "Статистика недоступна"
|
||
},
|
||
"systemHealth": {
|
||
"title": "Состояние системы",
|
||
"containers": "Контейнеры",
|
||
"proxies": "Прокси",
|
||
"recentErrors": "Недавние ошибки"
|
||
},
|
||
"daemons": {
|
||
"title": "Демоны",
|
||
"refresh": "Обновить",
|
||
"refreshing": "Обновление",
|
||
"docker": "Docker Engine",
|
||
"npm": "Nginx Proxy Manager",
|
||
"traefik": "Traefik",
|
||
"proxy": "Прокси",
|
||
"online": "Онлайн",
|
||
"offline": "Оффлайн",
|
||
"notConfigured": "Не настроено",
|
||
"containers": "Контейнеры",
|
||
"running": "Запущено",
|
||
"paused": "Пауза",
|
||
"stopped": "Остановлено",
|
||
"version": "Версия",
|
||
"apiVersion": "Версия API",
|
||
"platform": "Платформа",
|
||
"kernel": "Ядро",
|
||
"cpu": "CPU",
|
||
"memory": "Память",
|
||
"storage": "Хранилище",
|
||
"images": "Образы",
|
||
"latency": "Задержка",
|
||
"rootDir": "Корневой каталог",
|
||
"provider": "Провайдер",
|
||
"endpoint": "Адрес",
|
||
"proxyHosts": "Прокси-хосты",
|
||
"managed": "наши",
|
||
"external": "внешние",
|
||
"accessLists": "Списки доступа",
|
||
"certificates": "Сертификаты",
|
||
"dockerHint": "Проверьте, что Docker-демон запущен и сокет доступен.",
|
||
"proxyHint": "Проверьте URL прокси, учётные данные и доступность сервиса.",
|
||
"noProxyDesc": "Провайдер прокси не настроен. Tinyforge поддерживает Nginx Proxy Manager или Traefik.",
|
||
"configureProxy": "Настроить в параметрах",
|
||
"dockerNotReachable": "Docker-демон недоступен.",
|
||
"dockerUnreachable": "Docker недоступен",
|
||
"proxyUnreachable": "Прокси недоступен",
|
||
"reachable": "доступен"
|
||
},
|
||
"dns": {
|
||
"title": "DNS-записи",
|
||
"description": "Просмотр и управление DNS-записями, созданными Tinyforge.",
|
||
"wildcardActive": "Режим Wildcard DNS активен",
|
||
"wildcardActiveDesc": "DNS-записи управляются внешне через wildcard DNS. Отключите wildcard DNS в настройках для индивидуального управления записями.",
|
||
"refresh": "Обновить",
|
||
"syncNow": "Синхронизировать",
|
||
"syncing": "Синхронизация...",
|
||
"syncComplete": "Синхронизация завершена: {created} создано, {deleted} удалено, {synced} уже синхронизировано",
|
||
"syncFailed": "Ошибка синхронизации DNS",
|
||
"searchPlaceholder": "Поиск по FQDN...",
|
||
"allConsumers": "Все потребители",
|
||
"managed": "Управляемые (инстансы)",
|
||
"standalone": "Автономные прокси",
|
||
"orphaned": "Осиротевшие",
|
||
"allStatuses": "Все статусы",
|
||
"statusSynced": "Синхронизировано",
|
||
"statusMissing": "Отсутствует",
|
||
"statusOrphaned": "Осиротевшее",
|
||
"columnFqdn": "FQDN",
|
||
"columnType": "Тип",
|
||
"columnValue": "Значение",
|
||
"columnConsumer": "Потребитель",
|
||
"columnStatus": "Статус",
|
||
"columnActions": "Действия",
|
||
"noConsumer": "Нет потребителя",
|
||
"noRecords": "DNS-записи не найдены. Записи появятся здесь после развёртывания сервисов.",
|
||
"noMatchingRecords": "Нет записей, соответствующих текущим фильтрам.",
|
||
"deleteRecord": "Удалить запись",
|
||
"recordDeleted": "DNS-запись {fqdn} удалена",
|
||
"deleteFailed": "Не удалось удалить DNS-запись",
|
||
"loadFailed": "Не удалось загрузить DNS-записи",
|
||
"totalRecords": "Всего: {count}",
|
||
"syncedCount": "Синхронизировано: {count}",
|
||
"missingCount": "Отсутствует: {count}",
|
||
"orphanedCount": "Осиротевших: {count}"
|
||
},
|
||
"language": {
|
||
"en": "Английский",
|
||
"ru": "Русский"
|
||
},
|
||
"stacks": {
|
||
"eyebrow": "КУЗНИЦА",
|
||
"title": "Стеки",
|
||
"lede": "Compose-чертежи, выкованные как <em>атомарные единицы</em>. Запускайте сервисы, меняйте ревизии и откатывайтесь без нервов.",
|
||
"newStack": "Новый стек",
|
||
"refresh": "Обновить",
|
||
"total": "Всего",
|
||
"running": "Работают",
|
||
"deploying": "Куются",
|
||
"failed": "Сбой",
|
||
"stopped": "Холодные",
|
||
"empty": {
|
||
"title": "Наковальня остыла.",
|
||
"desc": "Загрузите docker-compose.yml, чтобы выковать первый стек."
|
||
},
|
||
"card": {
|
||
"noDescription": "Без описания",
|
||
"updated": "Обновлён",
|
||
"start": "Запустить",
|
||
"stop": "Остановить",
|
||
"delete": "Удалить",
|
||
"open": "Открыть"
|
||
},
|
||
"new": {
|
||
"eyebrow": "НОВЫЙ ЧЕРТЁЖ",
|
||
"title": "Выковать новый стек.",
|
||
"lede": "Загрузите или вставьте <code>docker-compose.yml</code>. Все сервисы чертежа разворачиваются как одна атомарная единица.",
|
||
"back": "Стеки",
|
||
"name": "Имя",
|
||
"namePlaceholder": "мой-стек",
|
||
"nameHint": "Строчные буквы, через дефис. Используется как имя compose-проекта.",
|
||
"description": "Описание",
|
||
"descriptionPlaceholder": "Что делает этот стек?",
|
||
"composeYaml": "Compose YAML",
|
||
"required": "обязательно",
|
||
"optional": "необязательно",
|
||
"loadSample": "Загрузить пример",
|
||
"uploadFile": "Загрузить файл",
|
||
"dropHere": "Перетащите сюда docker-compose.yml",
|
||
"dropSub": "или нажмите для выбора · или используйте <strong>Загрузить пример</strong> выше",
|
||
"lines": "{n} строк",
|
||
"bytes": "{n} байт",
|
||
"clear": "Очистить",
|
||
"deployImmediate": "Развернуть сразу",
|
||
"deployHint": "Куй железо, пока горячо. Без галочки стек сохраняется холодным.",
|
||
"cancel": "Отмена",
|
||
"forging": "Куём…",
|
||
"forgeAndDeploy": "Выковать и развернуть",
|
||
"saveBlueprint": "Сохранить чертёж",
|
||
"errorRequired": "Имя и compose YAML обязательны.",
|
||
"errorCreate": "Не удалось создать стек"
|
||
},
|
||
"detail": {
|
||
"manifest": "МАНИФЕСТ",
|
||
"loading": "Загрузка чертежа…",
|
||
"composeProject": "COMPOSE-ПРОЕКТ",
|
||
"noDescription": "Без описания",
|
||
"refresh": "Обновить",
|
||
"start": "Запустить",
|
||
"stop": "Остановить",
|
||
"delete": "Удалить",
|
||
"fault": "СБОЙ",
|
||
"err": "ОШБ",
|
||
"stats": {
|
||
"services": "Сервисы",
|
||
"servicesSub": "в чертеже",
|
||
"running": "Работают",
|
||
"runningSub": "активных контейнеров",
|
||
"revisions": "Ревизии",
|
||
"revisionsSub": "в истории",
|
||
"current": "Текущая",
|
||
"currentSub": "развёрнута"
|
||
},
|
||
"services": {
|
||
"title": "Сервисы",
|
||
"count": "{n} в работе",
|
||
"empty": "— нет запущенных контейнеров —"
|
||
},
|
||
"tabs": {
|
||
"blueprint": "Чертёж",
|
||
"revisions": "Ревизии",
|
||
"logs": "Логи"
|
||
},
|
||
"yaml": {
|
||
"currentRevision": "Текущая ревизия",
|
||
"edit": "Править и развернуть",
|
||
"cancel": "Отмена",
|
||
"forging": "Куём…",
|
||
"deployNew": "Развернуть новую ревизию"
|
||
},
|
||
"revisions": {
|
||
"current": "ТЕКУЩАЯ",
|
||
"by": "автор",
|
||
"rollback": "← Откатиться к этой ревизии",
|
||
"rollbackTitle": "Откатить ревизию?",
|
||
"rollbackMessage": "Создать новую ревизию из rev {n} и развернуть стек заново.",
|
||
"rollbackConfirm": "Откатить"
|
||
},
|
||
"logs": {
|
||
"service": "Сервис:",
|
||
"allServices": "Все сервисы",
|
||
"fetching": "Загрузка…",
|
||
"fetch": "Получить логи",
|
||
"empty": "— логи не загружены. нажмите получить. —"
|
||
},
|
||
"delete": {
|
||
"title": "Удалить стек?",
|
||
"messageBase": "Будет выполнен 'docker compose down' и удалён \"{name}\".",
|
||
"messageVolumes": " Именованные тома также будут удалены.",
|
||
"confirm": "Удалить"
|
||
},
|
||
"errors": {
|
||
"load": "Не удалось загрузить стек",
|
||
"stop": "Остановка не удалась",
|
||
"start": "Запуск не удался",
|
||
"update": "Обновление не удалось",
|
||
"rollback": "Откат не удался",
|
||
"delete": "Удаление не удалось",
|
||
"fetchLogs": "Не удалось загрузить логи"
|
||
}
|
||
}
|
||
},
|
||
"timezone": {
|
||
"eyebrow": "The Forge // Хронограф",
|
||
"title": "Часовой пояс отображения",
|
||
"subtitle": "Все даты в Tinyforge — лог событий, деплои, бэкапы, сайты — показываются в этом поясе.",
|
||
"modeLabel": "Режим определения",
|
||
"modeAuto": "Автоопределение",
|
||
"modeManual": "Вручную",
|
||
"autoDetect": "Автоопределение из браузера",
|
||
"autoBadge": "Авто",
|
||
"activeZone": "Активный пояс",
|
||
"changeZone": "Сменить часовой пояс",
|
||
"clickToChange": "Нажмите, чтобы выбрать пояс →",
|
||
"pickerTitle": "Выбор часового пояса",
|
||
"pickerPlaceholder": "Поиск — город, регион, смещение UTC…",
|
||
"groupAuto": "Определение",
|
||
"groupPopular": "Популярные",
|
||
"groupAll": "Все пояса",
|
||
"previewFull": "Полная метка времени",
|
||
"previewDate": "Только дата",
|
||
"previewHint": "Метки времени в логе событий будут выглядеть именно так."
|
||
},
|
||
"settingsDns": {
|
||
"title": "Настройка DNS",
|
||
"description": "Выберите, использовать ли wildcard-запись или отдельные поддомены, управляемые DNS-провайдером."
|
||
},
|
||
"settingsIntegrations": {
|
||
"title": "Интеграции",
|
||
"outgoing": "Исходящие уведомления",
|
||
"outgoingDesc": "Куда Tinyforge отправляет события деплоев и алертов. Укажите webhook-URL (Apprise, Discord, Slack, свой обработчик).",
|
||
"incoming": "Входящие вебхуки",
|
||
"incomingMovedDesc": "Входящие вебхуки теперь привязаны к конкретному проекту или сайту. Откройте страницу проекта или статического сайта, чтобы увидеть и перегенерировать URL."
|
||
},
|
||
"webhookPanel": {
|
||
"copy": "Копировать",
|
||
"copied": "Webhook-URL скопирован в буфер обмена",
|
||
"copyFailed": "Не удалось скопировать",
|
||
"noUrl": "Webhook-URL не настроен",
|
||
"loadFailed": "Не удалось загрузить webhook-URL",
|
||
"regenerate": "Перегенерировать URL",
|
||
"regenerated": "Webhook-URL перегенерирован",
|
||
"regenerateFailed": "Не удалось перегенерировать webhook-URL",
|
||
"regenerateWarning": "Перегенерация инвалидирует текущий URL. Обновите CI-пайплайны и Git-вебхуки, использующие его.",
|
||
"confirmRegenerate": "Заменить текущий URL?",
|
||
"confirmYes": "Перегенерировать",
|
||
"confirmNo": "Отмена"
|
||
},
|
||
"outgoingWebhook": {
|
||
"signingOn": "Подпись включена",
|
||
"signingOff": "Без подписи",
|
||
"signingSecret": "HMAC-секрет",
|
||
"noSecret": "Секрет не задан — исходящие события отправляются без подписи.",
|
||
"reveal": "Показать",
|
||
"generate": "Сгенерировать",
|
||
"copy": "Копировать",
|
||
"copied": "Секрет скопирован в буфер обмена",
|
||
"copyFailed": "Не удалось скопировать",
|
||
"loadFailed": "Не удалось загрузить секрет",
|
||
"regenerate": "Перегенерировать",
|
||
"regenerated": "Секрет перегенерирован",
|
||
"regenerateFailed": "Не удалось перегенерировать секрет",
|
||
"confirmRegenerateTitle": "Перегенерировать секрет?",
|
||
"confirmRegenerate": "Текущий секрет инвалидируется немедленно. Все получатели должны быть обновлены синхронно — иначе начнут отклонять события.",
|
||
"confirmDisableTitle": "Отключить HMAC-подпись?",
|
||
"confirmDisable": "Будущие события пойдут без заголовка X-Hub-Signature-256. Получатели, требующие подпись, начнут их отклонять.",
|
||
"confirmYes": "Подтвердить",
|
||
"confirmNo": "Отмена",
|
||
"disable": "Отключить подпись",
|
||
"disabled": "Подпись отключена",
|
||
"disableFailed": "Не удалось отключить подпись",
|
||
"sendTestTitle": "Отправить тестовое событие",
|
||
"sendTestHelp": "Отправляет синтетическое событие \"test\" на разрешённый URL с текущим секретом.",
|
||
"sendTest": "Отправить тест",
|
||
"sending": "Отправка…",
|
||
"testFailed": "Не удалось отправить тестовое событие",
|
||
"tier": "Уровень",
|
||
"signed": "Подписано",
|
||
"unsigned": "Без подписи",
|
||
"deliveryId": "Доставка",
|
||
"responseBody": "Тело ответа",
|
||
"networkError": "Сетевая ошибка",
|
||
"fallbackTo": "URL не задан на этом уровне — события унаследуются от {label}.",
|
||
"noUrlConfigured": "URL не задан. Настройте его выше перед тестом."
|
||
},
|
||
"settingsMaintenance": {
|
||
"title": "Обслуживание",
|
||
"thresholds": "Пороги",
|
||
"thresholdsDesc": "Настройте, когда Tinyforge помечает контейнеры как устаревшие и предупреждает о неиспользуемых образах.",
|
||
"dangerZone": "Опасная зона"
|
||
}
|
||
}
|