392 lines
11 KiB
Markdown
392 lines
11 KiB
Markdown
|
|
# Skyvern Frontend - Анализ интернационализации
|
|||
|
|
|
|||
|
|
**Дата**: 20 февраля 2026
|
|||
|
|
**Статус**: ❌ i18n НЕ реализован
|
|||
|
|
|
|||
|
|
## Текущее состояние
|
|||
|
|
|
|||
|
|
### ❌ Система переводов отсутствует
|
|||
|
|
|
|||
|
|
1. **Нет библиотек i18n**:
|
|||
|
|
- ❌ react-i18next
|
|||
|
|
- ❌ react-intl
|
|||
|
|
- ❌ i18next
|
|||
|
|
- ❌ Любых других библиотек интернационализации
|
|||
|
|
|
|||
|
|
2. **Все тексты хардкодные**:
|
|||
|
|
```tsx
|
|||
|
|
// Пример из src/routes/root/SideNav.tsx
|
|||
|
|
{
|
|||
|
|
label: "Discover",
|
|||
|
|
to: "/discover",
|
|||
|
|
icon: <CompassIcon className="size-6" />,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
label: "Workflows",
|
|||
|
|
to: "/workflows",
|
|||
|
|
icon: <LightningBoltIcon className="size-6" />,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
label: "Settings",
|
|||
|
|
to: "/settings",
|
|||
|
|
icon: <GearIcon className="size-6" />,
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **Прямые английские строки в JSX**:
|
|||
|
|
```tsx
|
|||
|
|
// src/routes/settings/Settings.tsx
|
|||
|
|
<CardTitle className="text-lg">Settings</CardTitle>
|
|||
|
|
<CardDescription>
|
|||
|
|
You can select environment and organization here
|
|||
|
|
</CardDescription>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Объем работы для русификации
|
|||
|
|
|
|||
|
|
### Статистика:
|
|||
|
|
- **487 файлов** (.tsx, .ts)
|
|||
|
|
- **~200+ компонентов** с текстовым контентом
|
|||
|
|
- **~1000+ строк** для перевода (примерная оценка)
|
|||
|
|
|
|||
|
|
### Основные файлы с текстами:
|
|||
|
|
|
|||
|
|
#### Навигация:
|
|||
|
|
- `src/routes/root/SideNav.tsx` - меню (Build, Discover, Workflows, Settings)
|
|||
|
|
- `src/routes/root/TopNav.tsx` - верхнее меню
|
|||
|
|
|
|||
|
|
#### Страницы:
|
|||
|
|
- `src/routes/settings/Settings.tsx` - настройки
|
|||
|
|
- `src/routes/workflows/` - вся система workflows
|
|||
|
|
- `src/routes/tasks/` - задачи
|
|||
|
|
- `src/routes/credentials/` - учетные данные
|
|||
|
|
- `src/routes/browserSessions/` - браузерные сессии
|
|||
|
|
|
|||
|
|
#### Компоненты UI:
|
|||
|
|
- `src/components/` - все компоненты (~150 файлов)
|
|||
|
|
|
|||
|
|
## Как добавить русский язык
|
|||
|
|
|
|||
|
|
### Вариант 1: react-i18next (рекомендуется)
|
|||
|
|
|
|||
|
|
**Преимущества:**
|
|||
|
|
- ✅ Самая популярная библиотека для React
|
|||
|
|
- ✅ Поддержка плюрализации (1 задача, 2 задачи, 5 задач)
|
|||
|
|
- ✅ Lazy loading переводов
|
|||
|
|
- ✅ TypeScript support
|
|||
|
|
- ✅ Легкая интеграция с существующим кодом
|
|||
|
|
|
|||
|
|
**Этапы внедрения:**
|
|||
|
|
|
|||
|
|
#### 1. Установить зависимости
|
|||
|
|
```bash
|
|||
|
|
cd /home/vodorod/dorod/skyvern/skyvern-frontend
|
|||
|
|
npm install react-i18next i18next i18next-http-backend i18next-browser-languagedetector
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2. Создать структуру переводов
|
|||
|
|
```
|
|||
|
|
src/
|
|||
|
|
i18n/
|
|||
|
|
config.ts # конфигурация i18next
|
|||
|
|
locales/
|
|||
|
|
en/
|
|||
|
|
common.json # общие тексты
|
|||
|
|
settings.json # настройки
|
|||
|
|
workflows.json # workflows
|
|||
|
|
tasks.json # задачи
|
|||
|
|
ru/
|
|||
|
|
common.json
|
|||
|
|
settings.json
|
|||
|
|
workflows.json
|
|||
|
|
tasks.json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3. Пример конфигурации (`src/i18n/config.ts`)
|
|||
|
|
```typescript
|
|||
|
|
import i18n from 'i18next';
|
|||
|
|
import { initReactI18next } from 'react-i18next';
|
|||
|
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
|||
|
|
|
|||
|
|
// Import translations
|
|||
|
|
import enCommon from './locales/en/common.json';
|
|||
|
|
import enSettings from './locales/en/settings.json';
|
|||
|
|
import ruCommon from './locales/ru/common.json';
|
|||
|
|
import ruSettings from './locales/ru/settings.json';
|
|||
|
|
|
|||
|
|
i18n
|
|||
|
|
.use(LanguageDetector)
|
|||
|
|
.use(initReactI18next)
|
|||
|
|
.init({
|
|||
|
|
resources: {
|
|||
|
|
en: {
|
|||
|
|
common: enCommon,
|
|||
|
|
settings: enSettings,
|
|||
|
|
},
|
|||
|
|
ru: {
|
|||
|
|
common: ruCommon,
|
|||
|
|
settings: ruSettings,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
fallbackLng: 'en',
|
|||
|
|
defaultNS: 'common',
|
|||
|
|
interpolation: {
|
|||
|
|
escapeValue: false,
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
export default i18n;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4. Подключить в `src/main.tsx`
|
|||
|
|
```tsx
|
|||
|
|
import './i18n/config'; // добавить ПЕРЕД другими импортами
|
|||
|
|
|
|||
|
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|||
|
|
<React.StrictMode>
|
|||
|
|
<App />
|
|||
|
|
</React.StrictMode>
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 5. Пример использования в компонентах
|
|||
|
|
|
|||
|
|
**Было:**
|
|||
|
|
```tsx
|
|||
|
|
function SideNav() {
|
|||
|
|
return (
|
|||
|
|
<NavLinkGroup
|
|||
|
|
title="Build"
|
|||
|
|
links={[
|
|||
|
|
{
|
|||
|
|
label: "Discover",
|
|||
|
|
to: "/discover",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
label: "Workflows",
|
|||
|
|
to: "/workflows",
|
|||
|
|
},
|
|||
|
|
]}
|
|||
|
|
/>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Стало:**
|
|||
|
|
```tsx
|
|||
|
|
import { useTranslation } from 'react-i18next';
|
|||
|
|
|
|||
|
|
function SideNav() {
|
|||
|
|
const { t } = useTranslation('common');
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<NavLinkGroup
|
|||
|
|
title={t('nav.build')}
|
|||
|
|
links={[
|
|||
|
|
{
|
|||
|
|
label: t('nav.discover'),
|
|||
|
|
to: "/discover",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
label: t('nav.workflows'),
|
|||
|
|
to: "/workflows",
|
|||
|
|
},
|
|||
|
|
]}
|
|||
|
|
/>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Файл `/src/i18n/locales/en/common.json`:**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"nav": {
|
|||
|
|
"build": "Build",
|
|||
|
|
"discover": "Discover",
|
|||
|
|
"workflows": "Workflows",
|
|||
|
|
"runs": "Runs",
|
|||
|
|
"browsers": "Browsers",
|
|||
|
|
"general": "General",
|
|||
|
|
"settings": "Settings",
|
|||
|
|
"credentials": "Credentials"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Файл `/src/i18n/locales/ru/common.json`:**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"nav": {
|
|||
|
|
"build": "Созда<D0B4><D0B0>ие",
|
|||
|
|
"discover": "Обзор",
|
|||
|
|
"workflows": "Рабочие процессы",
|
|||
|
|
"runs": "Запуски",
|
|||
|
|
"browsers": "Браузеры",
|
|||
|
|
"general": "Общее",
|
|||
|
|
"settings": "Настройки",
|
|||
|
|
"credentials": "Учетные данные"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 6. Добавить переключатель языка
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
import { useTranslation } from 'react-i18next';
|
|||
|
|
import { Select } from '@/components/ui/select';
|
|||
|
|
|
|||
|
|
function LanguageSwitcher() {
|
|||
|
|
const { i18n } = useTranslation();
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<Select
|
|||
|
|
value={i18n.language}
|
|||
|
|
onValueChange={(lang) => i18n.changeLanguage(lang)}
|
|||
|
|
>
|
|||
|
|
<SelectItem value="en">English</SelectItem>
|
|||
|
|
<SelectItem value="ru">Русский</SelectItem>
|
|||
|
|
</Select>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Вариант 2: react-intl (альтернатива)
|
|||
|
|
|
|||
|
|
**Преимущества:**
|
|||
|
|
- ✅ От Facebook/Meta
|
|||
|
|
- ✅ Встроенная поддержка форматирования (даты, числа, валюта)
|
|||
|
|
- ✅ ICU Message syntax
|
|||
|
|
|
|||
|
|
**Минусы:**
|
|||
|
|
- ❌ Более сложная настройка
|
|||
|
|
- ❌ Менее популярна чем react-i18next
|
|||
|
|
|
|||
|
|
### Вариант 3: Кастомное решение (НЕ рекомендуется)
|
|||
|
|
|
|||
|
|
Можно сделать собственную систему с `React.Context`, но это излишне при наличии готовых решений.
|
|||
|
|
|
|||
|
|
## Оценка времени для полной русификации
|
|||
|
|
|
|||
|
|
### Этап 1: Настройка инфраструктуры (2-4 часа)
|
|||
|
|
- Установка react-i18next
|
|||
|
|
- Создание конфигурации
|
|||
|
|
- Настройка структуры файлов
|
|||
|
|
- Добавление переключателя языка
|
|||
|
|
|
|||
|
|
### Этап 2: Извлечение и перевод строк (20-40 часов)
|
|||
|
|
- Извлечь все строки из ~200 компонентов
|
|||
|
|
- Создать JSON файлы с переводами
|
|||
|
|
- Перевести на русский (~1000+ строк)
|
|||
|
|
- Заменить хардкод на `t()` вызовы
|
|||
|
|
|
|||
|
|
### Этап 3: Тестирование (4-8 часов)
|
|||
|
|
- Проверка работы переводов
|
|||
|
|
- Тестирование переключения языков
|
|||
|
|
- Проверка плюрализации
|
|||
|
|
- Исправление багов с длиной строк (русские тексты длиннее)
|
|||
|
|
|
|||
|
|
**ИТОГО: 26-52 часа работы**
|
|||
|
|
|
|||
|
|
## Альтернативный подход: Постепенная русификация
|
|||
|
|
|
|||
|
|
Можно русифицировать постепенно, начиная с самых важных частей:
|
|||
|
|
|
|||
|
|
### Фаза 1: Навигация и меню (2-3 часа)
|
|||
|
|
- ✅ Левое меню (SideNav)
|
|||
|
|
- ✅ Верхнее меню (TopNav)
|
|||
|
|
- ✅ Переключатель языка
|
|||
|
|
|
|||
|
|
### Фаза 2: Страница настроек (3-4 часа)
|
|||
|
|
- ✅ Settings page
|
|||
|
|
- ✅ Формы
|
|||
|
|
|
|||
|
|
### Фаза 3: Workflows (8-12 часов)
|
|||
|
|
- ✅ Список workflows
|
|||
|
|
- ✅ Редактор workflows
|
|||
|
|
- ✅ Блоки и узлы
|
|||
|
|
|
|||
|
|
### Фаза 4: Остальные страницы (12-20 часов)
|
|||
|
|
- ✅ Tasks
|
|||
|
|
- ✅ Credentials
|
|||
|
|
- ✅ Browser Sessions
|
|||
|
|
|
|||
|
|
## Рекомендации
|
|||
|
|
|
|||
|
|
### ✅ Стоит делать если:
|
|||
|
|
1. Проект будет использоваться русскоязычными пользователями
|
|||
|
|
2. Есть время на поддержку двух языков
|
|||
|
|
3. Планируется добавление и других языков в будущем
|
|||
|
|
4. Нужен профессиональный вид для русских клиентов
|
|||
|
|
|
|||
|
|
### ❌ НЕ стоит делать если:
|
|||
|
|
1. Проект только для внутреннего использования англоязычной команды
|
|||
|
|
2. Нет времени на поддержку переводов при обновлениях
|
|||
|
|
3. Планируется переход на официальный SaaS Skyvern
|
|||
|
|
|
|||
|
|
## Пример быстрого старта
|
|||
|
|
|
|||
|
|
Если хотите попробовать - вот minimal пример для начала:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 1. Установить зависимости
|
|||
|
|
cd /home/vodorod/dorod/skyvern/skyvern-frontend
|
|||
|
|
npm install react-i18next i18next
|
|||
|
|
|
|||
|
|
# 2. Создать структуру
|
|||
|
|
mkdir -p src/i18n/locales/{en,ru}
|
|||
|
|
|
|||
|
|
# 3. Создать базовые переводы
|
|||
|
|
cat > src/i18n/locales/en/common.json << 'EOF'
|
|||
|
|
{
|
|||
|
|
"nav": {
|
|||
|
|
"discover": "Discover",
|
|||
|
|
"workflows": "Workflows",
|
|||
|
|
"runs": "Runs",
|
|||
|
|
"browsers": "Browsers",
|
|||
|
|
"settings": "Settings",
|
|||
|
|
"credentials": "Credentials"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
EOF
|
|||
|
|
|
|||
|
|
cat > src/i18n/locales/ru/common.json << 'EOF'
|
|||
|
|
{
|
|||
|
|
"nav": {
|
|||
|
|
"discover": "Обзор",
|
|||
|
|
"workflows": "Рабочие процессы",
|
|||
|
|
"runs": "Запуски",
|
|||
|
|
"browsers": "Браузеры",
|
|||
|
|
"settings": "Настройки",
|
|||
|
|
"credentials": "Учетные данные"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
EOF
|
|||
|
|
|
|||
|
|
# 4. Создать конфиг i18n
|
|||
|
|
# ... (см. пример выше)
|
|||
|
|
|
|||
|
|
# 5. Обновить один компонент для теста
|
|||
|
|
# ... (см. пример SideNav выше)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Заключение
|
|||
|
|
|
|||
|
|
**Текущее состояние:**
|
|||
|
|
- ❌ i18n НЕ реализован
|
|||
|
|
- ❌ Все тексты хардкодные английские
|
|||
|
|
- ❌ 1 язык - английский
|
|||
|
|
|
|||
|
|
**Возможность добавления русского:**
|
|||
|
|
- ✅ Технически ВОЗМОЖНО
|
|||
|
|
- ⚠️ Требует 26-52 часа работы для полной русификации
|
|||
|
|
- ✅ Можно делать постепенно (2-3 часа для начала)
|
|||
|
|
|
|||
|
|
**Рекомендация:**
|
|||
|
|
Если нужен русский интерфейс - начните с навигации (2-3 часа), а остальное добавляйте по мере необходимости.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Автор**: GitHub Copilot
|
|||
|
|
**Проект**: DOROD / Skyvern Integration
|
|||
|
|
**Обновлено**: 2026-02-20
|