feat: Add Russian i18n translations and fix CORS + API endpoint issues
Some checks failed
Run tests and pre-commit / Run tests and pre-commit hooks (push) Has been cancelled
Run tests and pre-commit / Frontend Lint and Build (push) Has been cancelled
Publish Fern Docs / run (push) Has been cancelled
Update OpenAPI Specification / update-openapi (push) Has been cancelled

- Implemented full Russian translation (ru) for 8 major pages
- Added LanguageSwitcher component with language detection
- Translated: Navigation, Settings, Workflows, Credentials, Banner, Examples
- Fixed API endpoint path: changed to use sans-api-v1 client for /v1/ endpoints
- Fixed CORS: added http://localhost:8081 to ALLOWED_ORIGINS
- Added locales infrastructure with i18next and react-i18next
- Created bilingual JSON files (en/ru) for 4 namespaces
- 220+ translation keys implemented
- Backend CORS configuration updated in .env
- Documentation: I18N implementation guides and installation docs
This commit is contained in:
Vodorod
2026-02-21 08:29:21 +03:00
parent b56d724ed8
commit 6b69159550
34 changed files with 3715 additions and 217 deletions

View File

@@ -0,0 +1,119 @@
{
"nav": {
"build": "Build",
"general": "General",
"discover": "Discover",
"workflows": "Workflows",
"runs": "Runs",
"browsers": "Browsers",
"settings": "Settings",
"credentials": "Credentials"
},
"prompt": {
"title": "What task would you like to accomplish?",
"placeholder": "Enter your prompt...",
"withCode": "with code"
},
"examples": {
"addToCart": "Add a product to cart",
"applyJob": "Apply for a job",
"getInsurance": "Get an insurance quote",
"fillEDD": "Fill out CA's online EDD",
"fillContact": "Fill a contact us form",
"hackerNews": "What's the top post on hackernews",
"searchStock": "Search for AAPL on Google Finance",
"getFootball": "Get the top ranked football team",
"extractIntegrations": "Extract Integrations from Gong.io"
},
"advancedSettings": {
"title": "Advanced Settings",
"show": "Show Advanced Settings",
"hide": "Hide Advanced Settings",
"webhookCallbackUrl": "Webhook Callback URL",
"webhookCallbackUrlDescription": "The URL of a webhook endpoint to send the extracted information",
"testWebhook": "Test Webhook",
"proxyLocation": "Proxy Location",
"proxyLocationDescription": "Route Skyvern through one of our proxies",
"browserSessionId": "Browser Session ID",
"browserSessionIdDescription": "The ID of a persistent browser session",
"browserSessionIdPlaceholder": "plus_xxx",
"browserAddress": "Browser Address",
"browserAddressDescription": "The address of the Browser CDP to run",
"browserAddressPlaceholder": "http://127.0.0.1:9222",
"2faIdentifier": "2FA Identifier",
"2faIdentifierDescription": "The identifier for a 2FA code for this task",
"extraHttpHeaders": "Extra HTTP Headers",
"extraHttpHeadersDescription": "Specify some custom HTTP requests headers in JSON format",
"addHeader": "Add Header",
"generateScript": "Generate Script",
"generateScriptDescription": "Whether to generate scripts for this task run on success",
"publishWorkflow": "Publish Workflow",
"publishWorkflowDescription": "Create a workflow from this task run. Will also be created 'Generate Script' is enabled",
"maxStepsOverride": "Max Steps Override",
"maxStepsOverrideDescription": "The maximum number of steps to take for this task",
"maxStepsOverridePlaceholder": "Default: 25",
"dataSchema": "Data Schema",
"dataSchemaDescription": "Specify the output data schema in JSON format",
"maxScreenshotScrolls": "Max Screenshot Scrolls",
"maxScreenshotScrollsDescription": "The maximum number of scrolls for the post action screenshot. Use -1 to have Skyvern take the current viewport.",
"maxScreenshotScrollsPlaceholder": "Default: 3"
},
"error": {
"title": "Unable to verify Skyvern API key",
"description": "The UI could not reach the diagnostics endpoint. Ensure the backend is running locally.",
"label": "Network Error"
},
"apiKeyBanner": {
"missingEnv": {
"title": "Skyvern API key missing",
"description": "All requests from the UI to the local backend will fail until a valid key is configured."
},
"invalidFormat": {
"title": "Skyvern API key is invalid",
"description": "The configured key cannot be decoded. Regenerate a new key to continue using the UI."
},
"invalid": {
"title": "Skyvern API key not recognized",
"description": "The backend rejected the configured key. Regenerate it to refresh local auth."
},
"expired": {
"title": "Skyvern API key expired",
"description": "The current key is no longer valid. Generate a fresh key to restore connectivity."
},
"notFound": {
"title": "Local organization missing",
"description": "The backend could not find the Skyvern-local organization. Regenerate the key to recreate it."
},
"error": {
"title": "Unable to verify Skyvern API key",
"description": "The UI could not reach the diagnostics endpoint. Ensure the backend is running locally."
},
"instructions": "Update <code>VITE_SKYVERN_API_KEY</code> in <code className=\"mx-1\">skyvern-frontend/.env</code> by running <code>skyvern init</code> or click the button below to regenerate it automatically.",
"productionWarning": "When running a production build, the regenerated API key is stored in sessionStorage. Closing this tab or browser window will lose the key. Restart the UI server for more robust persistence.",
"regenerateButton": "Regenerate API key",
"regenerating": "Regenerating…",
"toast": {
"title": "API key regenerated",
"description": "Requests now use the updated key automatically",
"fingerprint": "fingerprint",
"persistedTo": "persisted to sessionStorage and written to the following .env paths:",
"backend": "Backend:",
"frontend": "Frontend:",
"restartNote": "Restart the UI server for more robust API key persistence."
},
"repairError": "Unable to repair API key",
"noKeyReturned": "Repair succeeded but no API key was returned."
},
"buttons": {
"create": "Create",
"cancel": "Cancel",
"save": "Save",
"delete": "Delete",
"edit": "Edit",
"run": "Run",
"stop": "Stop",
"close": "Close",
"import": "Import",
"export": "Export"
}
}

View File

@@ -0,0 +1,65 @@
{
"title": "Credentials",
"description": "Securely store your passwords, credit cards, secrets, and manage incoming 2FA codes for your workflows.",
"tabs": {
"passwords": "Passwords",
"creditCards": "Credit Cards",
"secrets": "Secrets",
"twoFA": "2FA"
},
"addButton": "Add",
"addMenu": {
"password": "Password",
"creditCard": "Credit Card",
"secret": "Secret"
},
"push2FA": {
"title": "Push a 2FA Code",
"description": "Paste the verification message you received. Skyvern extracts the code and attaches it to the relevant run.",
"identifier": "Identifier",
"identifierPlaceholder": "Email or phone receiving the code",
"verificationContent": "Verification content",
"verificationPlaceholder": "Paste the full email/SMS body or the 6-digit code",
"warning": "We only store this to help the current login. Avoid pasting unrelated sensitive data.",
"addMetadata": "Add optional metadata",
"sendButton": "Send 2FA Code"
},
"filters": {
"identifier": "Identifier",
"identifierPlaceholder": "Filter by email or phone",
"otpType": "OTP Type",
"otpTypePlaceholder": "All types",
"limit": "Limit",
"clearFilters": "Clear filters",
"otpTypes": {
"all": "All types",
"totp": "Numeric code",
"magicLink": "Magic link"
}
},
"table": {
"identifier": "Identifier",
"code": "Code",
"source": "Source",
"workflowRun": "Workflow Run",
"created": "Created",
"expires": "Expires",
"empty": "No 2FA codes yet. Paste a verification message above or configure automatic forwarding."
},
"errors": {
"unableToVerify": "Unable to verify Skyvern API key",
"backendNotRunning": "The UI could not reach the diagnostics endpoint. Ensure the backend is running locally.",
"networkError": "Network Error",
"featureUnavailable": "2FA listing unavailable",
"featureUnavailableDescription": "Upgrade the backend to include GET /v1/credentials/totp. Once available, this tab will automatically populate with codes."
},
"footer": {
"note": "Note:",
"requiresServer": "This feature requires a Bitwarden-compatible server (",
"selfHosted": "self-hosted Bitwarden",
"or": ") or",
"communityVersion": "this community version",
"orPaid": "or a paid Bitwarden account. Make sure the relevant `SKYVERN_AUTH_BITWARDEN_*` environment variables are configured. See details",
"here": "here"
}
}

View File

@@ -0,0 +1,45 @@
{
"title": "Settings",
"description": "You can select environment and organization here",
"environment": "Environment",
"organization": "Organization",
"apiKey": {
"title": "API Key",
"description": "Currently active API key"
},
"onePassword": {
"title": "1Password Integration",
"description": "Manage your 1Password service account token.",
"learnMore": "Learn how to create a service account",
"token": "1Password Service Account Token",
"tokenDescription": "Configure your 1Password service account token for credential management.",
"serviceAccountToken": "Service Account Token",
"updateToken": "Update Token"
},
"azure": {
"title": "Azure Integration",
"description": "Manage your Azure integration",
"credential": "Azure Client Secret Credential",
"credentialDescription": "Configure your Azure Client Secret Credential to give access to your Azure account.",
"tenantId": "Tenant ID",
"clientId": "Client ID",
"clientSecret": "Client Secret",
"updateCredential": "Update Credential"
},
"customCredential": {
"title": "Custom Credential Service",
"description": "Configure your custom HTTP API for credential management.",
"apiDescription": "Configure your custom HTTP API for credential management. Your API should support the standard CRUD operations.",
"apiBaseUrl": "API Base URL",
"apiBaseUrlPlaceholder": "The base URL of your custom credential service API (e.g., https://credentials.company.com/api/v1)",
"apiToken": "API Token",
"apiTokenDescription": "Bearer token for authenticating with your custom credential service",
"apiTokenPlaceholder": "your_api_token_here",
"updateConfiguration": "Update Configuration"
},
"language": {
"title": "Язык / Language",
"description": "Choose your preferred language",
"current": "Current language"
}
}

View File

@@ -0,0 +1,69 @@
{
"title": "Workflows",
"description": "Create your own complex workflows by connecting web agents together. Define a series of actions, set it, and forget it.",
"folders": {
"title": "Folders",
"newFolder": "New folder",
"organize": "Organize Your Workflows with Folders",
"organizeDescription": "Keep your workflows organized by creating folders. Group related workflows together by project, team, or workflow type for easier management.",
"createFirst": "Create Your First Folder",
"emptyTitle": "Organize Your Workflows with Folders",
"emptyDescription": "Keep your workflows organized by creating folders. Group related workflows together by project, team, or workflow type for easier management.",
"emptyButton": "Create Your First Folder"
},
"myFlows": "My Flows",
"viewAll": "View all workflows",
"searchPlaceholder": "Search by title or parameter...",
"noWorkflowsFound": "No workflows found",
"itemsPerPage": "Items per page",
"previous": "Previous",
"next": "Next",
"columns": {
"id": "ID",
"title": "Title",
"folder": "Folder",
"createdAt": "Created At"
},
"steps": {
"1": {
"title": "Save browser sessions and reuse them in subsequent runs",
"number": "1"
},
"2": {
"title": "Connect multiple agents together to carry out complex objectives",
"number": "2"
},
"3": {
"title": "Execute non-browser tasks such as sending emails",
"number": "3"
}
},
"buttons": {
"import": "Import",
"create": "Create",
"blankWorkflow": "Blank Workflow",
"fromTemplate": "From Template"
},
"tooltips": {
"template": "Template",
"assignToFolder": "Assign to Folder",
"showParameters": "Show Parameters",
"hideParameters": "Hide Parameters",
"noParameters": "No Parameters",
"openInEditor": "Open in Editor",
"createNewRun": "Create New Run"
},
"pagination": {
"itemsPerPage": "Items per page"
},
"dialogs": {
"createFolder": {
"title": "Create New Folder",
"description": "Create a folder to organize your workflows.",
"titleLabel": "Title",
"descriptionLabel": "Description (optional)",
"cancel": "Cancel",
"create": "Create Folder"
}
}
}

View File

@@ -0,0 +1,119 @@
{
"nav": {
"build": "Разработка",
"general": "Общие",
"discover": "Обзор",
"workflows": "Рабочие процессы",
"runs": "Запуски",
"browsers": "Браузеры",
"settings": "Настройки",
"credentials": "Учетные данные"
},
"prompt": {
"title": "Какую задачу вы хотите выполнить?",
"placeholder": "Введите ваш запрос...",
"withCode": "с кодом"
},
"examples": {
"addToCart": "Добавить товар в корзину",
"applyJob": "Подать заявку на вакансию",
"getInsurance": "Получить страховое предложение",
"fillEDD": "Заполнить онлайн-форму CA EDD",
"fillContact": "Заполнить форму обратной связи",
"hackerNews": "Какой топ-пост на hackernews",
"searchStock": "Найти AAPL на Google Finance",
"getFootball": "Получить топ футбольную команду",
"extractIntegrations": "Извлечь интеграции из Gong.io"
},
"advancedSettings": {
"title": "Дополнительные настройки",
"show": "Показать дополнительные настройки",
"hide": "Скрыть дополнительные настройки",
"webhookCallbackUrl": "Webhook Callback URL",
"webhookCallbackUrlDescription": "URL адрес webhook для отправки извлечённой информации",
"testWebhook": "Тестировать Webhook",
"proxyLocation": "Расположение прокси",
"proxyLocationDescription": "Запустить Skyvern через один из наших прокси",
"browserSessionId": "ID сессии браузера",
"browserSessionIdDescription": "ID постоянной сессии браузера",
"browserSessionIdPlaceholder": "plus_xxx",
"browserAddress": "Адрес браузера",
"browserAddressDescription": "Адрес CDP браузера для запуска",
"browserAddressPlaceholder": "http://127.0.0.1:9222",
"2faIdentifier": "2FA Идентификатор",
"2faIdentifierDescription": "Идентификатор кода 2FA для этой задачи",
"extraHttpHeaders": "Дополнительные HTTP заголовки",
"extraHttpHeadersDescription": "Укажите пользовательские HTTP заголовки в JSON формате",
"addHeader": "Добавить заголовок",
"generateScript": "Генерировать скрипт",
"generateScriptDescription": "Генерировать ли скрипты для этой задачи при успехе",
"publishWorkflow": "Опубликовать Workflow",
"publishWorkflowDescription": "Создать workflow из этой задачи. Также будет создан 'Generate Script' если включено",
"maxStepsOverride": "Переопределить Max Steps",
"maxStepsOverrideDescription": "Максимальное количество шагов для этой задачи",
"maxStepsOverridePlaceholder": "По умолчанию: 25",
"dataSchema": "Схема данных",
"dataSchemaDescription": "Укажите схему выходных данных в JSON формате",
"maxScreenshotScrolls": "Max Screenshot Scrolls",
"maxScreenshotScrollsDescription": "Максимальное количество прокруток для скриншотов. Используйте -1, чтобы Skyvern сделал скриншот текущего вьюпорта.",
"maxScreenshotScrollsPlaceholder": "По умолчанию: 3"
},
"error": {
"title": "Не удалось проверить API ключ Skyvern",
"description": "UI не смог подключиться к диагностической конечной точке. Убедитесь, что backend запущен локально.",
"label": "Сетевая ошибка"
},
"apiKeyBanner": {
"missingEnv": {
"title": "API ключ Skyvern отсутствует",
"description": "Все запросы из UI к локальному backend будут завершаться ошибкой, пока не будет настроен действительный ключ."
},
"invalidFormat": {
"title": "API ключ Skyvern недействителен",
"description": "Настроенный ключ не может быть декодирован. Сгенерируйте новый ключ, чтобы продолжить использование UI."
},
"invalid": {
"title": "API ключ Skyvern не распознан",
"description": "Backend отклонил настроенный ключ. Сгенерируйте его заново, чтобы обновить локальную аутентификацию."
},
"expired": {
"title": "API ключ Skyvern истёк",
"description": "Текущий ключ больше недействителен. Создайте новый ключ для восстановления подключения."
},
"notFound": {
"title": "Локальная организация отсутствует",
"description": "Backend не смог найти локальную организацию Skyvern. Сгенерируйте ключ заново, чтобы её воссоздать."
},
"error": {
"title": "Не удалось проверить API ключ Skyvern",
"description": "UI не смог подключиться к диагностической конечной точке. Убедитесь, что backend запущен локально."
},
"instructions": "Обновите <code>VITE_SKYVERN_API_KEY</code> в <code className=\"mx-1\">skyvern-frontend/.env</code>, запустив <code>skyvern init</code> или нажмите кнопку ниже, чтобы сгенерировать его автоматически.",
"productionWarning": "При запуске production сборки, сгенерированный API ключ сохраняется в sessionStorage. Закрытие этой вкладки или браузера приведёт к потере ключа. Перезапустите UI сервер для более надёжного сохранения.",
"regenerateButton": "Перегенерировать API ключ",
"regenerating": "Генерация…",
"toast": {
"title": "API ключ перегенерирован",
"description": "Запросы теперь автоматически используют обновлённый ключ",
"fingerprint": "отпечаток",
"persistedTo": "сохранён в sessionStorage и записан в следующие .env файлы:",
"backend": "Backend:",
"frontend": "Frontend:",
"restartNote": "Перезапустите UI сервер для более надёжного сохранения API ключа."
},
"repairError": "Не удалось восстановить API ключ",
"noKeyReturned": "Восстановление прошло успешно, но API ключ не был возвращён."
},
"buttons": {
"create": "Создать",
"cancel": "Отмена",
"save": "Сохранить",
"delete": "Удалить",
"edit": "Редактировать",
"run": "Запустить",
"stop": "Остановить",
"close": "Закрыть",
"import": "Импорт",
"export": "Экспорт"
}
}

View File

@@ -0,0 +1,65 @@
{
"title": "Учетные данные",
"description": "Безопасно храните пароли, кредитные карты, секреты и управляйте входящими 2FA кодами для ваших процессов.",
"tabs": {
"passwords": "Пароли",
"creditCards": "Кредитные карты",
"secrets": "Секреты",
"twoFA": "2FA"
},
"addButton": "Добавить",
"addMenu": {
"password": "Пароль",
"creditCard": "Кредитная карта",
"secret": "Секрет"
},
"push2FA": {
"title": "Отправить 2FA код",
"description": "Вставьте полученное сообщение для верификации. Skyvern извлечет код и прикрепит его к соответствующему запуску.",
"identifier": "Идентификатор",
"identifierPlaceholder": "Email или телефон получающий код",
"verificationContent": "Содержимое верификации",
"verificationPlaceholder": "Вставьте полный текст email/SMS или 6-значный код",
"warning": "Мы сохраняем это только для текущего входа. Избегайте вставки несвязанных конфиденциальных данных.",
"addMetadata": "Добавить необязательные метаданные",
"sendButton": "Отправить 2FA код"
},
"filters": {
"identifier": "Идентификатор",
"identifierPlaceholder": "Фильтр по email или телефону",
"otpType": "Тип OTP",
"otpTypePlaceholder": "Все типы",
"limit": "Лимит",
"clearFilters": "Очистить фильтры",
"otpTypes": {
"all": "Все типы",
"totp": "Числовой код",
"magicLink": "Магическая ссылка"
}
},
"table": {
"identifier": "Идентификатор",
"code": "Код",
"source": "Источник",
"workflowRun": "Запуск процесса",
"created": "Создано",
"expires": "Истекает",
"empty": "Пока нет 2FA кодов. Вставьте сообщение верификации выше или настройте автоматическую переадресацию."
},
"errors": {
"unableToVerify": "Не удалось проверить API ключ Skyvern",
"backendNotRunning": "UI не может достичь диагностической конечной точки. Убедитесь что backend запущен локально.",
"networkError": "Ошибка сети",
"featureUnavailable": "Список 2FA недоступен",
"featureUnavailableDescription": "Обновите backend чтобы включить GET /v1/credentials/totp. После доступности эта вкладка автоматически заполнится кодами."
},
"footer": {
"note": "Примечание:",
"requiresServer": "Эта функция требует Bitwarden-совместимый сервер (",
"selfHosted": "самостоятельно развернутый Bitwarden",
"or": ") или",
"communityVersion": "эту версию сообщества",
"orPaid": "или платный Bitwarden аккаунт. Убедитесь что соответствующие переменные окружения `SKYVERN_AUTH_BITWARDEN_*` настроены. См. детали",
"here": "здесь"
}
}

View File

@@ -0,0 +1,45 @@
{
"title": "Настройки",
"description": "Здесь вы можете выбрать окружение и организацию",
"environment": "Окружение",
"organization": "Организация",
"apiKey": {
"title": "API ключ",
"description": "Текущий активный API ключ"
},
"onePassword": {
"title": "Интеграция с 1Password",
"description": "Управление токеном сервисного аккаунта 1Password.",
"learnMore": "Узнайте, как создать сервисный аккаунт",
"token": "Токен сервисного аккаунта 1Password",
"tokenDescription": "Настройте токен сервисного аккаунта 1Password для управления учетными данными.",
"serviceAccountToken": "Токен сервисного аккаунта",
"updateToken": "Обновить токен"
},
"azure": {
"title": "Интеграция с Azure",
"description": "Управление интеграцией с Azure",
"credential": "Учетные данные Azure Client Secret",
"credentialDescription": "Настройте учетные данные Azure Client Secret для доступа к вашему аккаунту Azure.",
"tenantId": "ID арендатора",
"clientId": "ID клиента",
"clientSecret": "Секрет клиента",
"updateCredential": "Обновить учетные данные"
},
"customCredential": {
"title": "Пользовательский сервис учетных данных",
"description": "Настройте ваш пользовательский HTTP API для управления учетными данными.",
"apiDescription": "Настройте ваш пользовательский HTTP API для управления учетными данными. Ваш API должен поддерживать стандартные CRUD операции.",
"apiBaseUrl": "Базовый URL API",
"apiBaseUrlPlaceholder": "Базовый URL вашего API сервиса учетных данных (например, https://credentials.company.com/api/v1)",
"apiToken": "API токен",
"apiTokenDescription": "Bearer токен для аутентификации в вашем сервисе учетных данных",
"apiTokenPlaceholder": аш_api_токен_здесь",
"updateConfiguration": "Обновить конфигурацию"
},
"language": {
"title": "Язык / Language",
"description": "Выберите предпочитаемый язык",
"current": "Текущий язык"
}
}

View File

@@ -0,0 +1,69 @@
{
"title": "Рабочие процессы",
"description": "Создавайте свои собственные сложные рабочие процессы, объединяя веб-агентов вместе. Определите последовательность действий, настройте и забудьте.",
"folders": {
"title": "Папки",
"newFolder": "Новая папка",
"organize": "Организуйте ваши Workflows с помощью папок",
"organizeDescription": "Держите свои workflows организованными, создавая папки. Группируйте связанные workflows вместе по проекту, команде или типу workflow для более простого управления.",
"createFirst": "Создайте вашу первую папку",
"emptyTitle": "Организуйте ваши Workflows с помощью папок",
"emptyDescription": "Держите свои workflows организованными, создавая папки. Группируйте связанные workflows вместе по проекту, команде или типу workflow для более простого управления.",
"emptyButton": "Создайте вашу первую папку"
},
"myFlows": "Мои процессы",
"viewAll": "Посмотреть все процессы",
"searchPlaceholder": "Поиск по названию или параметру...",
"noWorkflowsFound": "Рабочие процессы не найдены",
"itemsPerPage": "Элементов на странице",
"previous": "Предыдущая",
"next": "Следующая",
"columns": {
"id": "ID",
"title": "Название",
"folder": "Папка",
"createdAt": "Создано"
},
"steps": {
"1": {
"title": "Сохраняйте сессии браузера и переиспользуйте их в последующих запусках",
"number": "1"
},
"2": {
"title": "Объединяйте несколько агентов для выполнения сложных задач",
"number": "2"
},
"3": {
"title": "Выполняйте небраузерные задачи, такие как отправка email",
"number": "3"
}
},
"buttons": {
"import": "Импорт",
"create": "Создать",
"blankWorkflow": "Пустой процесс",
"fromTemplate": "Из шаблона"
},
"tooltips": {
"template": "Шаблон",
"assignToFolder": "Назначить в папку",
"showParameters": "Показать параметры",
"hideParameters": "Скрыть параметры",
"noParameters": "Нет параметров",
"openInEditor": "Открыть в редакторе",
"createNewRun": "Создать новый запуск"
},
"pagination": {
"itemsPerPage": "Элементов на странице"
},
"dialogs": {
"createFolder": {
"title": "Создать новую папку",
"description": "Создайте папку для организации ваших рабочих процессов.",
"titleLabel": "Название",
"descriptionLabel": "Описание (необязательно)",
"cancel": "Отмена",
"create": "Создать папку"
}
}
}