feat: add translation language setting & onboarding flow
- Add separate translation_language setting (independent from interface language) - Implement 3-step onboarding for new users: 1. Choose interface language 2. Choose learning language 3. Choose translation language - Fix localization issues when using callback.message (user_id from state) - Add UserService.get_user_by_id() method - Add get_user_translation_lang() helper in i18n - Update all handlers to use correct translation language - Add localization keys for onboarding (ru/en/ja) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@ from database.models import WordSource
|
||||
from services.user_service import UserService
|
||||
from services.vocabulary_service import VocabularyService
|
||||
from services.ai_service import ai_service
|
||||
from utils.i18n import t, get_user_lang
|
||||
from utils.i18n import t, get_user_lang, get_user_translation_lang
|
||||
from utils.levels import get_user_level_for_language
|
||||
|
||||
router = Router()
|
||||
@@ -87,7 +87,7 @@ async def process_text(message: Message, state: FSMContext):
|
||||
level=current_level,
|
||||
max_words=15,
|
||||
learning_lang=user.learning_language,
|
||||
translation_lang=user.language_interface,
|
||||
translation_lang=get_user_translation_lang(user),
|
||||
)
|
||||
|
||||
await processing_msg.delete()
|
||||
@@ -176,27 +176,29 @@ async def import_single_word(callback: CallbackQuery, state: FSMContext):
|
||||
user_id = data.get('user_id')
|
||||
|
||||
if word_index >= len(words):
|
||||
await callback.answer("❌ Ошибка: слово не найдено")
|
||||
await callback.answer(t('ru', 'words.err_not_found'))
|
||||
return
|
||||
|
||||
word_data = words[word_index]
|
||||
|
||||
async with async_session_maker() as session:
|
||||
user = await UserService.get_user_by_telegram_id(session, callback.from_user.id)
|
||||
lang = get_user_lang(user)
|
||||
|
||||
# Проверяем, нет ли уже такого слова
|
||||
existing = await VocabularyService.get_word_by_original(
|
||||
session, user_id, word_data['word']
|
||||
)
|
||||
|
||||
if existing:
|
||||
await callback.answer(f"Слово '{word_data['word']}' уже в словаре", show_alert=True)
|
||||
await callback.answer(t(lang, 'words.already_exists', word=word_data['word']), show_alert=True)
|
||||
return
|
||||
|
||||
# Добавляем слово
|
||||
learn = user.learning_language if user else 'en'
|
||||
ui = user.language_interface if user else 'ru'
|
||||
translation_lang = get_user_translation_lang(user)
|
||||
ctx = word_data.get('context')
|
||||
examples = ([{learn: ctx, ui: ''}] if ctx else [])
|
||||
examples = ([{learn: ctx, translation_lang: ''}] if ctx else [])
|
||||
|
||||
await VocabularyService.add_word(
|
||||
session=session,
|
||||
@@ -204,7 +206,7 @@ async def import_single_word(callback: CallbackQuery, state: FSMContext):
|
||||
word_original=word_data['word'],
|
||||
word_translation=word_data['translation'],
|
||||
source_lang=user.learning_language if user else None,
|
||||
translation_lang=user.language_interface if user else None,
|
||||
translation_lang=translation_lang,
|
||||
transcription=word_data.get('transcription'),
|
||||
examples=examples,
|
||||
source=WordSource.CONTEXT,
|
||||
@@ -242,9 +244,9 @@ async def import_all_words(callback: CallbackQuery, state: FSMContext):
|
||||
|
||||
# Добавляем слово
|
||||
learn = user.learning_language if user else 'en'
|
||||
ui = user.language_interface if user else 'ru'
|
||||
translation_lang = get_user_translation_lang(user)
|
||||
ctx = word_data.get('context')
|
||||
examples = ([{learn: ctx, ui: ''}] if ctx else [])
|
||||
examples = ([{learn: ctx, translation_lang: ''}] if ctx else [])
|
||||
|
||||
await VocabularyService.add_word(
|
||||
session=session,
|
||||
@@ -252,7 +254,7 @@ async def import_all_words(callback: CallbackQuery, state: FSMContext):
|
||||
word_original=word_data['word'],
|
||||
word_translation=word_data['translation'],
|
||||
source_lang=user.learning_language if user else None,
|
||||
translation_lang=user.language_interface if user else None,
|
||||
translation_lang=translation_lang,
|
||||
transcription=word_data.get('transcription'),
|
||||
examples=examples,
|
||||
source=WordSource.CONTEXT,
|
||||
@@ -389,7 +391,7 @@ async def handle_file_import(message: Message, state: FSMContext, bot: Bot):
|
||||
translations = await ai_service.translate_words_batch(
|
||||
words=words_to_translate,
|
||||
source_lang=user.learning_language,
|
||||
translation_lang=user.language_interface
|
||||
translation_lang=get_user_translation_lang(user)
|
||||
)
|
||||
|
||||
await processing_msg.delete()
|
||||
@@ -490,7 +492,7 @@ async def import_file_all_words(callback: CallbackQuery, state: FSMContext):
|
||||
word_original=word_data['word'],
|
||||
word_translation=word_data.get('translation', ''),
|
||||
source_lang=user.learning_language if user else None,
|
||||
translation_lang=user.language_interface if user else None,
|
||||
translation_lang=get_user_translation_lang(user),
|
||||
transcription=word_data.get('transcription'),
|
||||
source=WordSource.IMPORT
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user