227 lines
6.2 KiB
Markdown
227 lines
6.2 KiB
Markdown
# Быстрый старт: Система локализации
|
||
|
||
## Что уже работает ✅
|
||
|
||
1. **Выбор языка при первом запуске** - новые пользователи видят меню из 10 языков
|
||
2. **Сохранение языка в БД** - колонка `users.lang` хранит выбор пользователя
|
||
3. **10 поддерживаемых языков** - ru, en, es, fr, de, it, pt, ko, zh, ja
|
||
4. **Инфраструктура i18next** - готова к использованию
|
||
|
||
## Что нужно сделать ⚠️
|
||
|
||
### ГЛАВНАЯ ЗАДАЧА: Заменить 255 хардкод-текстов
|
||
|
||
**Файлы по приоритету:**
|
||
1. `src/handlers/callbackHandlers.ts` - 90 текстов (кнопки, меню)
|
||
2. `src/handlers/notificationHandlers.ts` - 31 текст (уведомления)
|
||
3. `src/services/notificationService.ts` - 22 текста (сервис уведомлений)
|
||
4. `src/handlers/messageHandlers.ts` - 21 текст (создание профиля)
|
||
5. Остальные файлы - ~91 текст
|
||
|
||
## Как использовать локализацию в коде
|
||
|
||
### Вариант 1: Через LocalizationService
|
||
|
||
```typescript
|
||
import LocalizationService from '../services/localizationService';
|
||
|
||
// В методе класса:
|
||
const locService = LocalizationService.getInstance();
|
||
const userId = msg.from?.id.toString();
|
||
const lang = await this.profileService.getUserLanguage(userId);
|
||
|
||
locService.setLanguage(lang);
|
||
const text = locService.t('profile.namePrompt');
|
||
|
||
await this.bot.sendMessage(chatId, text);
|
||
```
|
||
|
||
### Вариант 2: Через getUserTranslation (рекомендуется)
|
||
|
||
```typescript
|
||
import { getUserTranslation } from '../services/localizationService';
|
||
|
||
const userId = msg.from?.id.toString();
|
||
const text = await getUserTranslation(userId, 'profile.namePrompt');
|
||
|
||
await this.bot.sendMessage(chatId, text);
|
||
```
|
||
|
||
### Вариант 3: С параметрами
|
||
|
||
```typescript
|
||
// В ru.json:
|
||
{
|
||
"welcome": {
|
||
"greeting": "Привет, {{name}}! Добро пожаловать!"
|
||
}
|
||
}
|
||
|
||
// В коде:
|
||
const text = await getUserTranslation(userId, 'welcome.greeting', { name: userName });
|
||
```
|
||
|
||
## Процесс замены текста
|
||
|
||
### ШАГ 1: Найти хардкод-текст
|
||
|
||
```bash
|
||
# Найти все тексты в файле
|
||
grep -n "'[А-Яа-яЁё]\|\"[А-Яа-яЁё]" src/handlers/callbackHandlers.ts
|
||
```
|
||
|
||
### ШАГ 2: Добавить ключ в ru.json
|
||
|
||
**Было в коде:**
|
||
```typescript
|
||
await bot.sendMessage(chatId, '👤 Введите ваше имя:');
|
||
```
|
||
|
||
**Добавляем в ru.json:**
|
||
```json
|
||
{
|
||
"profile": {
|
||
"prompts": {
|
||
"name": "👤 Введите ваше имя:"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### ШАГ 3: Заменить в коде
|
||
|
||
```typescript
|
||
const text = await getUserTranslation(userId, 'profile.prompts.name');
|
||
await bot.sendMessage(chatId, text);
|
||
```
|
||
|
||
### ШАГ 4: Добавить перевод в en.json
|
||
|
||
```json
|
||
{
|
||
"profile": {
|
||
"prompts": {
|
||
"name": "👤 Enter your name:"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### ШАГ 5: Протестировать
|
||
|
||
```bash
|
||
# Пересобрать
|
||
docker compose up -d --build bot
|
||
|
||
# Проверить
|
||
docker compose logs bot --tail 20
|
||
```
|
||
|
||
## Полезные команды
|
||
|
||
```bash
|
||
# Найти все хардкод-тексты
|
||
./bin/find_hardcoded_texts.sh
|
||
|
||
# Посмотреть тексты в конкретном файле
|
||
grep -n "'[А-Яа-яЁё]\|\"[А-Яа-яЁё]" src/handlers/callbackHandlers.ts
|
||
|
||
# Собрать и запустить бота
|
||
docker compose up -d --build bot
|
||
|
||
# Проверить логи
|
||
docker compose logs bot --tail 50 -f
|
||
|
||
# Применить миграцию БД (если еще не применена)
|
||
PGPASSWORD='Cl0ud_1985!' psql -h 192.168.0.102 -p 5432 -U trevor \
|
||
-d telegram_tinder_bot -f sql/add_user_language.sql
|
||
```
|
||
|
||
## Структура ключей (рекомендуется)
|
||
|
||
```json
|
||
{
|
||
"language": { ... }, // Управление языком
|
||
"welcome": { ... }, // Приветствия
|
||
"profile": {
|
||
"prompts": { ... }, // Запросы ввода
|
||
"validation": { ... }, // Ошибки валидации
|
||
"labels": { ... } // Метки полей
|
||
},
|
||
"buttons": { ... }, // Кнопки
|
||
"errors": { ... }, // Общие ошибки
|
||
"commands": { ... }, // Команды бота
|
||
"search": { ... }, // Поиск анкет
|
||
"matches": { ... }, // Матчи
|
||
"notifications": { ... }, // Уведомления
|
||
"settings": { ... }, // Настройки
|
||
"vip": { ... } // VIP функции
|
||
}
|
||
```
|
||
|
||
## Пример: Замена кнопок
|
||
|
||
**Было:**
|
||
```typescript
|
||
const keyboard = {
|
||
inline_keyboard: [
|
||
[{ text: '❤️ Нравится', callback_data: 'like' }],
|
||
[{ text: '👎 Не нравится', callback_data: 'dislike' }]
|
||
]
|
||
};
|
||
```
|
||
|
||
**Добавили в ru.json:**
|
||
```json
|
||
{
|
||
"buttons": {
|
||
"like": "❤️ Нравится",
|
||
"dislike": "👎 Не нравится"
|
||
}
|
||
}
|
||
```
|
||
|
||
**Стало:**
|
||
```typescript
|
||
const userId = msg.from?.id.toString();
|
||
const lang = await this.profileService.getUserLanguage(userId);
|
||
this.localizationService.setLanguage(lang);
|
||
|
||
const keyboard = {
|
||
inline_keyboard: [
|
||
[{
|
||
text: this.localizationService.t('buttons.like'),
|
||
callback_data: 'like'
|
||
}],
|
||
[{
|
||
text: this.localizationService.t('buttons.dislike'),
|
||
callback_data: 'dislike'
|
||
}]
|
||
]
|
||
};
|
||
```
|
||
|
||
## Документация
|
||
|
||
- **docs/LOCALIZATION_SYSTEM.md** - Полное описание системы
|
||
- **docs/LOCALIZATION_MIGRATION_PLAN.md** - Детальный план замены текстов
|
||
- **docs/LOCALIZATION_REPORT.md** - Отчет о выполненной работе
|
||
|
||
## Следующий шаг
|
||
|
||
**Начните с самого крупного файла:**
|
||
|
||
```bash
|
||
# Посмотреть все тексты
|
||
grep -n "'[А-Яа-яЁё]\|\"[А-Яа-яЁё]" src/handlers/callbackHandlers.ts
|
||
|
||
# Открыть файл
|
||
code src/handlers/callbackHandlers.ts
|
||
```
|
||
|
||
**Заменяйте по 10-20 текстов за раз, тестируйте после каждой замены!**
|
||
|
||
---
|
||
|
||
Удачи! 🚀
|