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:
@@ -9,7 +9,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
|
||||
from utils.i18n import t, get_user_lang, get_user_translation_lang
|
||||
from utils.levels import get_user_level_for_language
|
||||
|
||||
router = Router()
|
||||
@@ -64,7 +64,7 @@ async def generate_words_for_theme(message: Message, state: FSMContext, theme: s
|
||||
level=current_level,
|
||||
count=10,
|
||||
learning_lang=user.learning_language,
|
||||
translation_lang=user.language_interface,
|
||||
translation_lang=get_user_translation_lang(user),
|
||||
)
|
||||
|
||||
await generating_msg.delete()
|
||||
@@ -83,15 +83,15 @@ async def generate_words_for_theme(message: Message, state: FSMContext, theme: s
|
||||
await state.set_state(WordsStates.viewing_words)
|
||||
|
||||
# Показываем подборку
|
||||
await show_words_list(message, words, theme)
|
||||
await show_words_list(message, words, theme, user_id)
|
||||
|
||||
|
||||
async def show_words_list(message: Message, words: list, theme: str):
|
||||
async def show_words_list(message: Message, words: list, theme: str, user_id: int):
|
||||
"""Показать список слов с кнопками для добавления"""
|
||||
|
||||
# Определяем язык интерфейса для заголовка/подсказок
|
||||
async with async_session_maker() as session:
|
||||
user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
|
||||
user = await UserService.get_user_by_telegram_id(session, user_id)
|
||||
lang = (user.language_interface if user else 'ru') or 'ru'
|
||||
|
||||
text = t(lang, 'words.header', theme=theme) + "\n\n"
|
||||
@@ -171,9 +171,9 @@ async def add_single_word(callback: CallbackQuery, state: FSMContext):
|
||||
# Добавляем слово
|
||||
# Формируем examples с учётом языков
|
||||
learn = user.learning_language if user else 'en'
|
||||
ui = user.language_interface if user else 'ru'
|
||||
translation_lang = get_user_translation_lang(user)
|
||||
ex = word_data.get('example')
|
||||
examples = ([{learn: ex, ui: ''}] if ex else [])
|
||||
examples = ([{learn: ex, translation_lang: ''}] if ex else [])
|
||||
|
||||
await VocabularyService.add_word(
|
||||
session=session,
|
||||
@@ -181,7 +181,7 @@ async def add_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.SUGGESTED,
|
||||
@@ -222,9 +222,9 @@ async def add_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)
|
||||
ex = word_data.get('example')
|
||||
examples = ([{learn: ex, ui: ''}] if ex else [])
|
||||
examples = ([{learn: ex, translation_lang: ''}] if ex else [])
|
||||
|
||||
await VocabularyService.add_word(
|
||||
session=session,
|
||||
@@ -232,7 +232,7 @@ async def add_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.SUGGESTED,
|
||||
@@ -241,9 +241,10 @@ async def add_all_words(callback: CallbackQuery, state: FSMContext):
|
||||
)
|
||||
added_count += 1
|
||||
|
||||
result_text = f"✅ Добавлено слов: <b>{added_count}</b>"
|
||||
lang = (user.language_interface if user else 'ru') or 'ru'
|
||||
result_text = t(lang, 'import.added_count', n=added_count)
|
||||
if skipped_count > 0:
|
||||
result_text += f"\n⚠️ Пропущено (уже в словаре): {skipped_count}"
|
||||
result_text += "\n" + t(lang, 'import.skipped_count', n=skipped_count)
|
||||
|
||||
await callback.message.edit_reply_markup(reply_markup=None)
|
||||
await callback.message.answer(result_text)
|
||||
|
||||
Reference in New Issue
Block a user