feat: JLPT levels for Japanese, custom practice scenarios, UI improvements
- Add separate level systems: CEFR (A1-C2) for European languages, JLPT (N5-N1) for Japanese - Store levels per language in new `levels_by_language` JSON field - Add custom scenario option in AI practice mode - Show action buttons after practice ends (new dialogue, tasks, words) - Fix level display across all handlers to use correct level system - Add Alembic migration for levels_by_language field - Update all locale files (ru, en, ja) with new keys 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,8 @@ 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
|
||||
from utils.levels import get_user_level_for_language
|
||||
|
||||
router = Router()
|
||||
|
||||
@@ -44,7 +45,10 @@ async def cmd_import(message: Message, state: FSMContext):
|
||||
async def cancel_import(message: Message, state: FSMContext):
|
||||
"""Отмена импорта"""
|
||||
await state.clear()
|
||||
await message.answer("❌ Импорт отменён.")
|
||||
async with async_session_maker() as session:
|
||||
user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
|
||||
lang = get_user_lang(user)
|
||||
await message.answer(t(lang, 'import_extra.cancelled'))
|
||||
|
||||
|
||||
@router.message(ImportStates.waiting_for_text)
|
||||
@@ -52,12 +56,16 @@ async def process_text(message: Message, state: FSMContext):
|
||||
"""Обработка текста от пользователя"""
|
||||
text = message.text.strip()
|
||||
|
||||
async with async_session_maker() as session:
|
||||
user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
|
||||
lang = get_user_lang(user)
|
||||
|
||||
if len(text) < 50:
|
||||
await message.answer(t('ru', 'import.too_short'))
|
||||
await message.answer(t(lang, 'import.too_short'))
|
||||
return
|
||||
|
||||
if len(text) > 3000:
|
||||
await message.answer(t('ru', 'import.too_long'))
|
||||
await message.answer(t(lang, 'import.too_long'))
|
||||
return
|
||||
|
||||
async with async_session_maker() as session:
|
||||
@@ -67,9 +75,10 @@ async def process_text(message: Message, state: FSMContext):
|
||||
processing_msg = await message.answer(t(user.language_interface or 'ru', 'import.processing'))
|
||||
|
||||
# Извлекаем слова через AI
|
||||
current_level = get_user_level_for_language(user)
|
||||
words = await ai_service.extract_words_from_text(
|
||||
text=text,
|
||||
level=user.level.value,
|
||||
level=current_level,
|
||||
max_words=15,
|
||||
learning_lang=user.learning_language,
|
||||
translation_lang=user.language_interface,
|
||||
@@ -87,7 +96,7 @@ async def process_text(message: Message, state: FSMContext):
|
||||
words=words,
|
||||
user_id=user.id,
|
||||
original_text=text,
|
||||
level=user.level.name
|
||||
level=current_level
|
||||
)
|
||||
await state.set_state(ImportStates.viewing_words)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user