feat(docker-watcher): phase 14 - frontend polish & modern UI

Design system with CSS custom properties (light/dark themes).
38 Lucide SVG icon components. Dark mode with system preference.
EN/RU localization with i18n store. Skeleton loaders, empty states,
toggle switches, micro-interactions. Responsive sidebar with
mobile hamburger menu. All pages polished with consistent styling.
This commit is contained in:
2026-03-27 23:53:09 +03:00
parent d4659146fc
commit a3aa5912d9
74 changed files with 2954 additions and 1750 deletions
+351
View File
@@ -0,0 +1,351 @@
{
"app": {
"name": "Docker Watcher",
"version": "v0.1"
},
"nav": {
"dashboard": "Dashboard",
"projects": "Projects",
"deploy": "Deploy",
"settings": "Settings"
},
"dashboard": {
"title": "Dashboard",
"quickDeploy": "Quick Deploy",
"totalProjects": "Total Projects",
"runningInstances": "Running Instances",
"failedInstances": "Failed Instances",
"projects": "Projects",
"retry": "Retry",
"noProjects": "No projects yet.",
"addFirst": "Add your first project",
"loadFailed": "Failed to load dashboard"
},
"projects": {
"title": "Projects",
"addProject": "Add Project",
"cancel": "Cancel",
"newProject": "New Project",
"name": "Name",
"image": "Image",
"port": "Port",
"registry": "Registry",
"created": "Created",
"view": "View",
"noProjects": "No projects configured yet.",
"getStarted": "Click \"Add Project\" to get started.",
"createProject": "Create Project",
"creating": "Creating...",
"healthcheck": "Healthcheck Path",
"nameRequired": "Name and image are required.",
"loadFailed": "Failed to load projects",
"createFailed": "Failed to create project"
},
"projectDetail": {
"deleteProject": "Delete Project",
"envVars": "Environment Variables",
"volumes": "Volume Mounts",
"stages": "Stages",
"noStages": "No stages configured for this project.",
"pattern": "Pattern",
"autoDeploy": "auto-deploy",
"requiresConfirm": "requires confirm",
"instances": "instances",
"deployNewVersion": "Deploy new version",
"selectTag": "Select tag to deploy",
"loadingTags": "Loading tags...",
"chooseTag": "Choose a tag...",
"enterTag": "Enter image tag (e.g., dev-abc123)",
"deploy": "Deploy",
"deploying": "Deploying...",
"recentDeploys": "Recent Deploys",
"noDeployHistory": "No deploy history for this project.",
"tag": "Tag",
"status": "Status",
"started": "Started",
"finished": "Finished",
"error": "Error",
"noInstancesRunning": "No instances running",
"deleteConfirmTitle": "Delete Project",
"deleteConfirmMessage": "This will permanently delete the project '{name}' and all its stages, instances, and deploy history. This cannot be undone.",
"loadFailed": "Failed to load project",
"deleteFailed": "Failed to delete project",
"deployFailed": "Deploy failed"
},
"envEditor": {
"title": "Environment Variables",
"description": "Manage per-stage environment variable overrides. Stage-level values override project-level defaults.",
"stage": "Stage",
"projectDefaults": "Project-Level Defaults",
"stageOverrides": "Stage Overrides",
"key": "Key",
"value": "Value",
"secret": "Secret",
"source": "Source",
"actions": "Actions",
"overridden": "overridden",
"inherited": "inherited",
"overridesProject": "overrides project",
"stageOnly": "stage only",
"edit": "Edit",
"change": "Change",
"delete": "Delete",
"save": "Save",
"add": "Add",
"adding": "Adding...",
"noStages": "No stages configured. Add stages to the project first.",
"loadFailed": "Failed to load project",
"envAdded": "Environment variable added",
"envUpdated": "Environment variable updated",
"envDeleted": "Environment variable deleted",
"addFailed": "Failed to add env var",
"updateFailed": "Failed to update env var",
"deleteFailed": "Failed to delete env var",
"loadEnvFailed": "Failed to load env vars"
},
"volumeEditor": {
"title": "Volume Mounts",
"description": "Configure volume mounts for containers.",
"sharedDesc": "Shared mode uses the source path as-is for all instances.",
"isolatedDesc": "Isolated mode appends /{stage}-{tag}/ to the source, giving each instance its own directory.",
"sourceHost": "Source (Host)",
"targetContainer": "Target (Container)",
"mode": "Mode",
"actions": "Actions",
"shared": "Shared",
"isolated": "Isolated",
"edit": "Edit",
"delete": "Delete",
"save": "Save",
"add": "Add",
"adding": "Adding...",
"noVolumes": "No volumes configured yet. Add one above.",
"volumeAdded": "Volume added",
"volumeUpdated": "Volume updated",
"volumeDeleted": "Volume deleted",
"loadFailed": "Failed to load volumes",
"addFailed": "Failed to add volume",
"updateFailed": "Failed to update volume",
"deleteFailed": "Failed to delete volume"
},
"quickDeploy": {
"title": "Quick Deploy",
"description": "Deploy a container image with zero configuration. Paste an image URL, review the defaults, and deploy.",
"step1": "1. Enter Image URL",
"imageUrl": "Image URL",
"imageUrlHelp": "Full image URL including tag (e.g., git.example.com/user/app:dev-abc123)",
"inspect": "Inspect",
"inspecting": "Inspecting...",
"step2": "2. Review Configuration",
"reviewDesc": "These defaults were detected from the image. Adjust as needed before deploying.",
"projectName": "Project Name",
"port": "Port",
"portHelp": "Container port to expose (1-65535)",
"healthCheckPath": "Health Check Path",
"healthCheckHelp": "Optional HTTP path for health verification",
"stage": "Stage",
"development": "Development",
"release": "Release",
"production": "Production",
"stageHelp": "Deployment stage for this image",
"subdomainOverride": "Subdomain Override",
"subdomainHelp": "Leave empty to use the default subdomain pattern",
"envVars": "Environment Variables",
"envVarsHelp": "One per line, KEY=VALUE format",
"step3": "3. Deploy",
"deployDesc": "A new project will be created and the container will be deployed immediately.",
"deployBtn": "Deploy",
"inspectedSuccess": "Image inspected successfully",
"deployedSuccess": "Deployed {name} successfully!",
"inspectFailed": "Failed to inspect image",
"deployFailed": "Deployment failed"
},
"settings": {
"title": "Settings",
"general": "General",
"registries": "Registries",
"credentials": "Credentials",
"authentication": "Authentication",
"appearance": "Appearance"
},
"settingsGeneral": {
"title": "General Settings",
"globalConfig": "Global Configuration",
"domain": "Domain",
"domainHelp": "Base domain for subdomain routing",
"serverIp": "Server IP",
"serverIpHelp": "Public IP address of the server",
"dockerNetwork": "Docker Network",
"dockerNetworkHelp": "Docker network for deployed containers",
"subdomainPattern": "Subdomain Pattern",
"subdomainPatternHelp": "Pattern for auto-generated subdomains",
"pollingInterval": "Polling Interval (seconds)",
"pollingIntervalHelp": "How often to check registries for new tags (10-86400)",
"notificationUrl": "Notification URL",
"notificationUrlHelp": "Webhook URL for deploy notifications",
"saveSettings": "Save Settings",
"saving": "Saving...",
"saved": "Settings saved successfully",
"saveFailed": "Failed to save settings",
"loadFailed": "Failed to load settings",
"webhookUrl": "Webhook URL",
"webhookDesc": "This secret URL receives image push notifications from your CI pipeline.",
"noWebhookUrl": "No webhook URL configured",
"copy": "Copy",
"copied": "Webhook URL copied to clipboard",
"regenerateUrl": "Regenerate URL",
"regenerating": "Regenerating...",
"regenerated": "Webhook URL regenerated",
"regenerateFailed": "Failed to regenerate webhook URL",
"regenerateWarning": "Warning: regenerating will invalidate the current URL. Update your CI pipelines."
},
"settingsRegistries": {
"title": "Container Registries",
"description": "Manage your container registries for image detection.",
"addRegistry": "Add Registry",
"editRegistry": "Edit Registry",
"addNewRegistry": "Add New Registry",
"name": "Name",
"nameHelp": "A friendly name for this registry",
"url": "URL",
"urlHelp": "Registry base URL",
"type": "Type",
"typeHelp": "Registry type for API compatibility",
"token": "Token",
"tokenHelpNew": "API token for authentication",
"tokenHelpEdit": "Leave empty to keep the existing token",
"save": "Save",
"saving": "Saving...",
"update": "Update",
"test": "Test",
"testing": "Testing...",
"edit": "Edit",
"delete": "Delete",
"noRegistries": "No registries configured yet.",
"addFirst": "Add your first registry",
"registryUpdated": "Registry updated",
"registryAdded": "Registry added",
"registryDeleted": "Registry \"{name}\" deleted",
"testSuccess": "Connection to \"{name}\" successful",
"saveFailed": "Failed to save registry",
"deleteFailed": "Failed to delete registry",
"testFailed": "Connection test failed",
"loadFailed": "Failed to load registries",
"deleteConfirm": "Delete registry \"{name}\"? This cannot be undone."
},
"settingsCredentials": {
"title": "Credentials",
"description": "Manage credentials for Nginx Proxy Manager and registry tokens. All values are encrypted at rest.",
"npm": "Nginx Proxy Manager",
"npmDesc": "Credentials for managing proxy hosts via NPM API",
"configured": "Configured",
"npmUrl": "NPM URL",
"npmUrlHelp": "Nginx Proxy Manager API URL",
"email": "Email",
"emailHelp": "NPM admin email",
"password": "Password",
"passwordHelpNew": "NPM admin password (will be encrypted)",
"passwordHelpEdit": "Enter the new password to replace the existing one",
"changeCredentials": "Change Credentials",
"save": "Save",
"saving": "Saving...",
"saved": "NPM credentials saved",
"saveFailed": "Failed to save NPM credentials",
"loadFailed": "Failed to load credentials",
"registryTokens": "Registry Tokens",
"registryTokensDesc": "Registry authentication tokens are managed per-registry in the",
"registriesLink": "Registries",
"registryTokensSuffix": "section. Each registry stores its token encrypted in the database."
},
"settingsAuth": {
"title": "Authentication Settings",
"description": "Configure authentication mode and manage users.",
"authMode": "Authentication Mode",
"local": "Local (username/password)",
"oidc": "OIDC (SSO)",
"oidcConfig": "OIDC Provider Configuration",
"issuerUrl": "Issuer URL",
"clientId": "Client ID",
"clientSecret": "Client Secret",
"redirectUrl": "Redirect URL",
"saveSettings": "Save Settings",
"saving": "Saving...",
"saved": "Settings saved",
"saveFailed": "Failed to save",
"loadFailed": "Failed to load settings",
"localUsers": "Local Users",
"username": "Username",
"email": "Email",
"role": "Role",
"created": "Created",
"noUsers": "No users found.",
"addUser": "Add User",
"viewer": "Viewer",
"admin": "Admin",
"userCreated": "User created",
"userDeleted": "User deleted",
"createFailed": "Failed to create user",
"deleteFailed": "Failed to delete user",
"deleteConfirm": "Are you sure you want to delete this user?",
"usernameRequired": "Username and password are required"
},
"login": {
"title": "Docker Watcher",
"subtitle": "Sign in to your account",
"username": "Username",
"password": "Password",
"signIn": "Sign in",
"signingIn": "Signing in...",
"or": "or",
"ssoButton": "Sign in with SSO (OIDC)",
"loginFailed": "Login failed",
"networkError": "Network error"
},
"common": {
"cancel": "Cancel",
"confirm": "Confirm",
"delete": "Delete",
"edit": "Edit",
"save": "Save",
"retry": "Retry",
"loading": "Loading...",
"noData": "No data",
"project": "Project",
"back": "Back",
"actions": "Actions",
"stop": "Stop",
"start": "Start",
"restart": "Restart",
"remove": "Remove"
},
"instance": {
"stopConfirm": "This will stop the running container. The instance can be started again later.",
"restartConfirm": "This will restart the container, causing brief downtime.",
"removeConfirm": "This will permanently remove the container and its proxy configuration. This cannot be undone.",
"actionFailed": "Action failed"
},
"empty": {
"noProjects": "No projects yet",
"noProjectsDesc": "Get started by creating your first project or use Quick Deploy.",
"createProject": "Create Project",
"noInstances": "No instances",
"noInstancesDesc": "Deploy a new version to see instances here.",
"noDeploys": "No deploy history",
"noDeploysDesc": "Deploy history will appear here after your first deployment.",
"noRegistries": "No registries",
"noRegistriesDesc": "Add a container registry to enable image detection.",
"noVolumes": "No volumes",
"noVolumesDesc": "Configure volume mounts for persistent data.",
"noUsers": "No users",
"noUsersDesc": "Add local users to manage access."
},
"theme": {
"light": "Light",
"dark": "Dark",
"system": "System"
},
"language": {
"en": "English",
"ru": "Russian"
}
}
+84
View File
@@ -0,0 +1,84 @@
/**
* Lightweight i18n system using Svelte stores.
* Task 13: EN/RU localization with locale switcher and localStorage persistence.
*/
import { writable, derived } from 'svelte/store';
import en from './en.json';
import ru from './ru.json';
export type Locale = 'en' | 'ru';
const LOCALE_KEY = 'dw_locale';
const translations: Record<Locale, Record<string, unknown>> = { en, ru };
function getInitialLocale(): Locale {
if (typeof localStorage !== 'undefined') {
const stored = localStorage.getItem(LOCALE_KEY);
if (stored === 'en' || stored === 'ru') return stored;
}
if (typeof navigator !== 'undefined') {
const lang = navigator.language.toLowerCase();
if (lang.startsWith('ru')) return 'ru';
}
return 'en';
}
export const locale = writable<Locale>(getInitialLocale());
// Persist locale changes to localStorage.
locale.subscribe((value) => {
if (typeof localStorage !== 'undefined') {
localStorage.setItem(LOCALE_KEY, value);
}
});
/**
* Look up a nested key like "dashboard.title" in the translation object.
*/
function getNestedValue(obj: Record<string, unknown>, path: string): string {
const parts = path.split('.');
let current: unknown = obj;
for (const part of parts) {
if (current === null || current === undefined || typeof current !== 'object') {
return path;
}
current = (current as Record<string, unknown>)[part];
}
return typeof current === 'string' ? current : path;
}
/**
* Derived store that returns a translation function.
* Usage: $t('dashboard.title') or $t('projectDetail.deleteConfirmMessage', { name: 'my-app' })
*/
export const t = derived(locale, ($locale) => {
const dict = translations[$locale] ?? translations.en;
return (key: string, params?: Record<string, string>): string => {
let result = getNestedValue(dict as Record<string, unknown>, key);
// Fallback to English if key not found in current locale.
if (result === key) {
result = getNestedValue(translations.en as Record<string, unknown>, key);
}
// Replace {param} placeholders.
if (params) {
for (const [paramKey, paramValue] of Object.entries(params)) {
result = result.replace(new RegExp(`\\{${paramKey}\\}`, 'g'), paramValue);
}
}
return result;
};
});
export function setLocale(newLocale: Locale): void {
locale.set(newLocale);
}
export const availableLocales: readonly Locale[] = ['en', 'ru'] as const;
+351
View File
@@ -0,0 +1,351 @@
{
"app": {
"name": "Docker Watcher",
"version": "v0.1"
},
"nav": {
"dashboard": "Панель",
"projects": "Проекты",
"deploy": "Деплой",
"settings": "Настройки"
},
"dashboard": {
"title": "Панель управления",
"quickDeploy": "Быстрый деплой",
"totalProjects": "Всего проектов",
"runningInstances": "Запущенных экземпляров",
"failedInstances": "Сбойных экземпляров",
"projects": "Проекты",
"retry": "Повторить",
"noProjects": "Проектов пока нет.",
"addFirst": "Добавьте первый проект",
"loadFailed": "Не удалось загрузить панель"
},
"projects": {
"title": "Проекты",
"addProject": "Добавить проект",
"cancel": "Отмена",
"newProject": "Новый проект",
"name": "Название",
"image": "Образ",
"port": "Порт",
"registry": "Реестр",
"created": "Создан",
"view": "Открыть",
"noProjects": "Проекты ещё не настроены.",
"getStarted": "Нажмите «Добавить проект» для начала.",
"createProject": "Создать проект",
"creating": "Создание...",
"healthcheck": "Путь проверки здоровья",
"nameRequired": "Название и образ обязательны.",
"loadFailed": "Не удалось загрузить проекты",
"createFailed": "Не удалось создать проект"
},
"projectDetail": {
"deleteProject": "Удалить проект",
"envVars": "Переменные окружения",
"volumes": "Тома",
"stages": "Стадии",
"noStages": "Для этого проекта не настроены стадии.",
"pattern": "Шаблон",
"autoDeploy": "авто-деплой",
"requiresConfirm": "нужно подтверждение",
"instances": "экземпляров",
"deployNewVersion": "Развернуть новую версию",
"selectTag": "Выберите тег для деплоя",
"loadingTags": "Загрузка тегов...",
"chooseTag": "Выберите тег...",
"enterTag": "Введите тег образа (напр., dev-abc123)",
"deploy": "Развернуть",
"deploying": "Развёртывание...",
"recentDeploys": "Последние деплои",
"noDeployHistory": "Нет истории деплоев для этого проекта.",
"tag": "Тег",
"status": "Статус",
"started": "Начат",
"finished": "Завершён",
"error": "Ошибка",
"noInstancesRunning": "Нет запущенных экземпляров",
"deleteConfirmTitle": "Удалить проект",
"deleteConfirmMessage": "Это безвозвратно удалит проект '{name}' и все его стадии, экземпляры и историю деплоев.",
"loadFailed": "Не удалось загрузить проект",
"deleteFailed": "Не удалось удалить проект",
"deployFailed": "Деплой не удался"
},
"envEditor": {
"title": "Переменные окружения",
"description": "Управление переопределениями переменных окружения на уровне стадий. Значения стадий переопределяют значения проекта.",
"stage": "Стадия",
"projectDefaults": "Значения проекта по умолчанию",
"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": "Не удалось загрузить переменные"
},
"volumeEditor": {
"title": "Тома",
"description": "Настройка монтирования томов для контейнеров.",
"sharedDesc": "Режим «Общий» использует путь источника как есть для всех экземпляров.",
"isolatedDesc": "Режим «Изолированный» добавляет /{stage}-{tag}/ к источнику, создавая свою директорию для каждого экземпляра.",
"sourceHost": "Источник (хост)",
"targetContainer": "Цель (контейнер)",
"mode": "Режим",
"actions": "Действия",
"shared": "Общий",
"isolated": "Изолированный",
"edit": "Изменить",
"delete": "Удалить",
"save": "Сохранить",
"add": "Добавить",
"adding": "Добавление...",
"noVolumes": "Тома ещё не настроены. Добавьте один выше.",
"volumeAdded": "Том добавлен",
"volumeUpdated": "Том обновлён",
"volumeDeleted": "Том удалён",
"loadFailed": "Не удалось загрузить тома",
"addFailed": "Не удалось добавить том",
"updateFailed": "Не удалось обновить том",
"deleteFailed": "Не удалось удалить том"
},
"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": "Развёртывание не удалось"
},
"settings": {
"title": "Настройки",
"general": "Общие",
"registries": "Реестры",
"credentials": "Учётные данные",
"authentication": "Аутентификация",
"appearance": "Внешний вид"
},
"settingsGeneral": {
"title": "Общие настройки",
"globalConfig": "Глобальная конфигурация",
"domain": "Домен",
"domainHelp": "Базовый домен для маршрутизации поддоменов",
"serverIp": "IP сервера",
"serverIpHelp": "Публичный IP-адрес сервера",
"dockerNetwork": "Docker-сеть",
"dockerNetworkHelp": "Docker-сеть для развёрнутых контейнеров",
"subdomainPattern": "Шаблон поддомена",
"subdomainPatternHelp": "Шаблон для автоматически генерируемых поддоменов",
"pollingInterval": "Интервал опроса (секунды)",
"pollingIntervalHelp": "Как часто проверять реестры на новые теги (10-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-пайплайны."
},
"settingsRegistries": {
"title": "Реестры контейнеров",
"description": "Управление реестрами контейнеров для обнаружения образов.",
"addRegistry": "Добавить реестр",
"editRegistry": "Редактировать реестр",
"addNewRegistry": "Добавить новый реестр",
"name": "Название",
"nameHelp": "Понятное название для этого реестра",
"url": "URL",
"urlHelp": "Базовый URL реестра",
"type": "Тип",
"typeHelp": "Тип реестра для совместимости API",
"token": "Токен",
"tokenHelpNew": "API-токен для аутентификации",
"tokenHelpEdit": "Оставьте пустым, чтобы сохранить текущий токен",
"save": "Сохранить",
"saving": "Сохранение...",
"update": "Обновить",
"test": "Тест",
"testing": "Тестирование...",
"edit": "Изменить",
"delete": "Удалить",
"noRegistries": "Реестры ещё не настроены.",
"addFirst": "Добавьте первый реестр",
"registryUpdated": "Реестр обновлён",
"registryAdded": "Реестр добавлен",
"registryDeleted": "Реестр «{name}» удалён",
"testSuccess": "Подключение к «{name}» успешно",
"saveFailed": "Не удалось сохранить реестр",
"deleteFailed": "Не удалось удалить реестр",
"testFailed": "Тест подключения не удался",
"loadFailed": "Не удалось загрузить реестры",
"deleteConfirm": "Удалить реестр «{name}»? Это действие необратимо."
},
"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": ". Каждый реестр хранит свой токен в зашифрованном виде."
},
"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": "Имя пользователя и пароль обязательны"
},
"login": {
"title": "Docker Watcher",
"subtitle": "Войдите в свой аккаунт",
"username": "Имя пользователя",
"password": "Пароль",
"signIn": "Войти",
"signingIn": "Вход...",
"or": "или",
"ssoButton": "Войти через SSO (OIDC)",
"loginFailed": "Ошибка входа",
"networkError": "Ошибка сети"
},
"common": {
"cancel": "Отмена",
"confirm": "Подтвердить",
"delete": "Удалить",
"edit": "Изменить",
"save": "Сохранить",
"retry": "Повторить",
"loading": "Загрузка...",
"noData": "Нет данных",
"project": "Проект",
"back": "Назад",
"actions": "Действия",
"stop": "Остановить",
"start": "Запустить",
"restart": "Перезапустить",
"remove": "Удалить"
},
"instance": {
"stopConfirm": "Контейнер будет остановлен. Экземпляр можно будет запустить снова позже.",
"restartConfirm": "Контейнер будет перезапущен с кратковременным простоем.",
"removeConfirm": "Контейнер и его прокси-конфигурация будут безвозвратно удалены.",
"actionFailed": "Действие не удалось"
},
"empty": {
"noProjects": "Проектов пока нет",
"noProjectsDesc": "Начните с создания первого проекта или используйте быстрый деплой.",
"createProject": "Создать проект",
"noInstances": "Нет экземпляров",
"noInstancesDesc": "Разверните новую версию, чтобы увидеть экземпляры здесь.",
"noDeploys": "Нет истории деплоев",
"noDeploysDesc": "История деплоев появится здесь после первого развёртывания.",
"noRegistries": "Нет реестров",
"noRegistriesDesc": "Добавьте реестр контейнеров для обнаружения образов.",
"noVolumes": "Нет томов",
"noVolumesDesc": "Настройте монтирование томов для постоянных данных.",
"noUsers": "Нет пользователей",
"noUsersDesc": "Добавьте локальных пользователей для управления доступом."
},
"theme": {
"light": "Светлая",
"dark": "Тёмная",
"system": "Системная"
},
"language": {
"en": "Английский",
"ru": "Русский"
}
}