Files
tg_tinder_bot/docs/LOCALIZATION_SYSTEM.md
2025-11-24 17:00:20 +09:00

330 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Система локализации 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