330 lines
11 KiB
Markdown
330 lines
11 KiB
Markdown
# Система локализации Telegram Tinder Bot
|
||
|
||
## Обзор
|
||
|
||
Реализована полноценная система мультиязычной поддержки бота с возможностью выбора языка интерфейса.
|
||
|
||
## Реализованные функции
|
||
|
||
### 1. База данных
|
||
|
||
**Миграция:** `sql/add_user_language.sql`
|
||
|
||
Добавлена колонка `lang` в таблицу `users`:
|
||
- Тип: `VARCHAR(5)`
|
||
- Значение по умолчанию: `'ru'` (Русский)
|
||
- NOT NULL constraint
|
||
- Индекс для быстрого поиска: `idx_users_lang`
|
||
|
||
```sql
|
||
ALTER TABLE users
|
||
ADD COLUMN IF NOT EXISTS lang VARCHAR(5) DEFAULT 'ru' NOT NULL;
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_users_lang ON users(lang);
|
||
```
|
||
|
||
### 2. Поддерживаемые языки
|
||
|
||
Бот поддерживает **10 языков**:
|
||
|
||
| Код | Язык | Флаг | Файл локализации |
|
||
|------|-----------|------|------------------|
|
||
| `ru` | Русский | 🇷🇺 | `ru.json` |
|
||
| `en` | English | 🇬🇧 | `en.json` |
|
||
| `es` | Español | 🇪🇸 | `es.json` |
|
||
| `fr` | Français | 🇫🇷 | `fr.json` |
|
||
| `de` | Deutsch | 🇩🇪 | `de.json` |
|
||
| `it` | Italiano | 🇮🇹 | `it.json` |
|
||
| `pt` | Português | 🇵🇹 | `pt.json` |
|
||
| `ko` | 한국어 | 🇰🇷 | `ko.json` |
|
||
| `zh` | 中文 | 🇨🇳 | `zh.json` |
|
||
| `ja` | 日本語 | 🇯🇵 | `ja.json` |
|
||
|
||
### 3. Архитектура
|
||
|
||
#### LocalizationService (`src/services/localizationService.ts`)
|
||
|
||
Сервис на базе `i18next`:
|
||
- Singleton pattern
|
||
- Автоматическая загрузка всех языковых файлов при инициализации
|
||
- Методы:
|
||
- `initialize()` - инициализация сервиса
|
||
- `t(key, options)` - получение перевода по ключу
|
||
- `setLanguage(lang)` - смена языка
|
||
- `getCurrentLanguage()` - получение текущего языка
|
||
- `getSupportedLanguages()` - список поддерживаемых языков
|
||
- `getTranslation(key, lang, options)` - получить перевод для конкретного языка без смены текущего
|
||
|
||
#### LanguageHandlers (`src/handlers/languageHandlers.ts`)
|
||
|
||
Обработчик выбора и управления языком:
|
||
- `showLanguageSelection(chatId, messageId?)` - показать меню выбора языка
|
||
- `handleSetLanguage(query)` - обработать установку языка
|
||
- `checkAndShowLanguageSelection(userId, chatId)` - проверить, нужно ли показывать выбор языка
|
||
|
||
#### ProfileService - Расширение (`src/services/profileService.ts`)
|
||
|
||
Добавлены методы для работы с языком пользователя:
|
||
- `ensureUser(telegramId, userData, language)` - создание/обновление пользователя с сохранением языка
|
||
- `updateUserLanguage(telegramId, language)` - обновление языка пользователя
|
||
- `getUserLanguage(telegramId)` - получение языка пользователя
|
||
|
||
### 4. Пользовательский опыт (UX)
|
||
|
||
#### Новый пользователь
|
||
|
||
1. Пользователь отправляет `/start`
|
||
2. **Автоматически показывается меню выбора языка** (10 кнопок с флагами)
|
||
3. После выбора языка:
|
||
- Язык сохраняется в БД
|
||
- Показывается приветственное сообщение на выбранном языке
|
||
- Предлагается создать профиль
|
||
|
||
#### Существующий пользователь
|
||
|
||
1. Пользователь отправляет `/start`
|
||
2. Бот использует сохраненный язык из БД
|
||
3. Показывается главное меню на выбранном языке
|
||
|
||
#### Изменение языка в настройках
|
||
|
||
Запланировано: добавить кнопку "🌍 Язык / Language" в раздел "⚙️ Настройки"
|
||
|
||
### 5. Структура локализационных файлов
|
||
|
||
Каждый файл `src/locales/{lang}.json` содержит:
|
||
|
||
```json
|
||
{
|
||
"language": {
|
||
"select": "🌍 Выберите язык...",
|
||
"changed": "✅ Язык изменен на...",
|
||
"ru": "🇷🇺 Русский",
|
||
"en": "🇬🇧 English",
|
||
...
|
||
},
|
||
"welcome": {
|
||
"greeting": "Добро пожаловать...",
|
||
"description": "...",
|
||
"getStarted": "..."
|
||
},
|
||
"profile": { ... },
|
||
"search": { ... },
|
||
"buttons": { ... },
|
||
"errors": { ... },
|
||
...
|
||
}
|
||
```
|
||
|
||
### 6. Интеграция в код
|
||
|
||
#### Импорт функции перевода
|
||
|
||
```typescript
|
||
import { getUserTranslation } from '../services/localizationService';
|
||
```
|
||
|
||
#### Использование в коде
|
||
|
||
```typescript
|
||
// Асинхронный вызов
|
||
const text = await getUserTranslation(userId, 'welcome.greeting');
|
||
|
||
// Или через сервис
|
||
const locService = LocalizationService.getInstance();
|
||
const text = locService.t('welcome.greeting');
|
||
```
|
||
|
||
#### Callback для выбора языка
|
||
|
||
Все callback_data для выбора языка имеют формат:
|
||
```
|
||
set_lang_{код_языка}
|
||
```
|
||
|
||
Например:
|
||
- `set_lang_ru` - установить русский
|
||
- `set_lang_en` - установить английский
|
||
- `set_lang_ko` - установить корейский
|
||
|
||
### 7. Запуск миграции
|
||
|
||
```bash
|
||
# Применить миграцию добавления колонки lang
|
||
PGPASSWORD='Cl0ud_1985!' psql -h 192.168.0.102 -p 5432 -U trevor -d telegram_tinder_bot -f sql/add_user_language.sql
|
||
```
|
||
|
||
### 8. Тестирование
|
||
|
||
#### Проверка выбора языка для нового пользователя:
|
||
|
||
1. Удалите свой профиль из БД:
|
||
```sql
|
||
DELETE FROM profiles WHERE user_id IN (
|
||
SELECT id FROM users WHERE telegram_id = YOUR_TELEGRAM_ID
|
||
);
|
||
DELETE FROM users WHERE telegram_id = YOUR_TELEGRAM_ID;
|
||
```
|
||
|
||
2. Отправьте `/start` боту
|
||
3. Должно появиться меню выбора из 10 языков
|
||
4. Выберите любой язык
|
||
5. Проверьте, что приветствие отображается на выбранном языке
|
||
|
||
#### Проверка сохранения языка:
|
||
|
||
```sql
|
||
SELECT telegram_id, username, lang FROM users;
|
||
```
|
||
|
||
## Следующие шаги
|
||
|
||
### Приоритет 1: Замена всех хардкод-текстов
|
||
|
||
Необходимо заменить все хардкод-тексты в следующих файлах:
|
||
|
||
1. **`src/handlers/messageHandlers.ts`** (профиль, регистрация)
|
||
2. **`src/handlers/callbackHandlers.ts`** (кнопки, меню)
|
||
3. **`src/handlers/commandHandlers.ts`** (команды)
|
||
4. **`src/services/notificationService.ts`** (уведомления)
|
||
|
||
### Приоритет 2: Дополнение языковых файлов
|
||
|
||
Текущие файлы содержат только базовые ключи. Нужно:
|
||
1. Извлечь все существующие тексты из кода
|
||
2. Добавить ключи в `ru.json` (эталонный файл)
|
||
3. Перевести ключи для остальных 9 языков
|
||
|
||
### Приоритет 3: Кнопка смены языка в настройках
|
||
|
||
Добавить в меню "⚙️ Настройки" кнопку:
|
||
```typescript
|
||
{ text: '🌍 Язык / Language', callback_data: 'change_language' }
|
||
```
|
||
|
||
## Состояние реализации
|
||
|
||
✅ **Выполнено:**
|
||
- Добавлена колонка `lang` в таблицу `users`
|
||
- Создан `LanguageHandlers` для управления языком
|
||
- Интегрирован выбор языка в `/start` для новых пользователей
|
||
- Обновлен `LocalizationService`
|
||
- Добавлены секции `language` в `ru.json` и `en.json`
|
||
- Методы работы с языком в `ProfileService`
|
||
|
||
⚠️ **В процессе:**
|
||
- Замена хардкод-текстов на локализационные ключи
|
||
- Дополнение всех языковых файлов
|
||
|
||
📋 **Планируется:**
|
||
- Кнопка смены языка в настройках
|
||
- Полный перевод всех 10 языков
|
||
- Тесты локализации
|
||
|
||
## Технические детали
|
||
|
||
### Callback Query Flow
|
||
|
||
```
|
||
Пользователь нажимает кнопку "🇷🇺 Русский"
|
||
↓
|
||
callback_data: 'set_lang_ru'
|
||
↓
|
||
callbackHandlers.handleCallback() перехватывает
|
||
↓
|
||
if (data.startsWith('set_lang_'))
|
||
↓
|
||
languageHandlers.handleSetLanguage(query)
|
||
↓
|
||
profileService.updateUserLanguage(userId, 'ru')
|
||
↓
|
||
localizationService.setLanguage('ru')
|
||
↓
|
||
Показ приветственного сообщения на русском
|
||
```
|
||
|
||
### Database Schema
|
||
|
||
```sql
|
||
CREATE TABLE users (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
telegram_id BIGINT UNIQUE NOT NULL,
|
||
username VARCHAR(255),
|
||
first_name VARCHAR(255),
|
||
last_name VARCHAR(255),
|
||
lang VARCHAR(5) DEFAULT 'ru' NOT NULL, -- ← НОВАЯ КОЛОНКА
|
||
is_active BOOLEAN DEFAULT true,
|
||
created_at TIMESTAMP DEFAULT NOW(),
|
||
last_active_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
|
||
CREATE INDEX idx_users_lang ON users(lang);
|
||
```
|
||
|
||
## Примеры использования
|
||
|
||
### Пример 1: Приветственное сообщение
|
||
|
||
```typescript
|
||
const lang = await profileService.getUserLanguage(userId);
|
||
localizationService.setLanguage(lang);
|
||
|
||
const greeting = localizationService.t('welcome.greeting');
|
||
const description = localizationService.t('welcome.description');
|
||
|
||
await bot.sendMessage(chatId, `${greeting}\n\n${description}`);
|
||
```
|
||
|
||
### Пример 2: Кнопки с переводом
|
||
|
||
```typescript
|
||
const keyboard: InlineKeyboardMarkup = {
|
||
inline_keyboard: [
|
||
[{
|
||
text: localizationService.t('buttons.save'),
|
||
callback_data: 'save_profile'
|
||
}],
|
||
[{
|
||
text: localizationService.t('buttons.cancel'),
|
||
callback_data: 'cancel'
|
||
}]
|
||
]
|
||
};
|
||
```
|
||
|
||
### Пример 3: Ошибки
|
||
|
||
```typescript
|
||
try {
|
||
// ... код
|
||
} catch (error) {
|
||
const errorMsg = localizationService.t('errors.serverError');
|
||
await bot.sendMessage(chatId, errorMsg);
|
||
}
|
||
```
|
||
|
||
## Поддержка
|
||
|
||
Если нужно добавить новый язык:
|
||
|
||
1. Создайте файл `src/locales/{код}.json`
|
||
2. Скопируйте структуру из `ru.json`
|
||
3. Переведите все ключи
|
||
4. Добавьте язык в `LocalizationService.initialize()`:
|
||
```typescript
|
||
const newLangTranslations = JSON.parse(
|
||
fs.readFileSync(path.join(localesPath, 'новый_код.json'), 'utf8')
|
||
);
|
||
```
|
||
5. Добавьте в `resources` объект
|
||
6. Добавьте в `getSupportedLanguages()`
|
||
7. Добавьте кнопку в `LanguageHandlers.showLanguageSelection()`
|
||
|
||
---
|
||
|
||
**Статус:** ✅ Система локализации активна и работает
|
||
|
||
**Версия:** 1.0.0
|
||
|
||
**Дата:** 06.11.2025
|