pre=deploy
This commit is contained in:
329
docs/LOCALIZATION_SYSTEM.md
Normal file
329
docs/LOCALIZATION_SYSTEM.md
Normal file
@@ -0,0 +1,329 @@
|
||||
# Система локализации 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
|
||||
Reference in New Issue
Block a user