feat(i18n): localize start/help/menu, practice, words, import, reminder, vocabulary, tasks/stats for RU/EN/JA; add JSON-based i18n helper\n\nfeat(lang): support learning/translation languages across AI flows; hide translations with buttons; store examples per lang\n\nfeat(vocab): add source_lang and translation_lang to Vocabulary, unique constraint (user_id, source_lang, word_original); filter /vocabulary by user.learning_language\n\nchore(migrations): add Alembic setup + migration to add vocab lang columns; env.py reads app settings and supports asyncpg URLs\n\nfix(words/import): pass learning_lang + translation_lang everywhere; fix menu themes generation\n\nfeat(settings): add learning language selector; update main menu on language change

This commit is contained in:
2025-12-04 19:40:01 +03:00
parent 6223351ccf
commit 472771229f
22 changed files with 1587 additions and 471 deletions

View File

@@ -75,7 +75,9 @@ class TaskService:
async def generate_mixed_tasks(
session: AsyncSession,
user_id: int,
count: int = 5
count: int = 5,
learning_lang: str = 'en',
translation_lang: str = 'ru'
) -> List[Dict]:
"""
Генерация заданий разных типов (переводы + заполнение пропусков)
@@ -109,23 +111,31 @@ class TaskService:
task_type = random.choice(['translate', 'fill_in'])
if task_type == 'translate':
# Задание на перевод
direction = random.choice(['en_to_ru', 'ru_to_en'])
# Задание на перевод между языком обучения и языком перевода
direction = random.choice(['learn_to_tr', 'tr_to_learn'])
if direction == 'en_to_ru':
# Локализация фразы "Переведи слово"
if translation_lang == 'en':
prompt = "Translate the word:"
elif translation_lang == 'ja':
prompt = "単語を訳してください:"
else:
prompt = "Переведи слово:"
if direction == 'learn_to_tr':
task = {
'type': 'translate_to_ru',
'type': f'translate_to_{translation_lang}',
'word_id': word.id,
'question': f"Переведи слово: <b>{word.word_original}</b>",
'question': f"{prompt} <b>{word.word_original}</b>",
'word': word.word_original,
'correct_answer': word.word_translation,
'transcription': word.transcription
}
else:
task = {
'type': 'translate_to_en',
'type': f'translate_to_{learning_lang}',
'word_id': word.id,
'question': f"Переведи слово: <b>{word.word_translation}</b>",
'question': f"{prompt} <b>{word.word_translation}</b>",
'word': word.word_translation,
'correct_answer': word.word_original,
'transcription': word.transcription
@@ -133,13 +143,25 @@ class TaskService:
else:
# Задание на заполнение пропуска
# Генерируем предложение с пропуском через AI
sentence_data = await ai_service.generate_fill_in_sentence(word.word_original)
sentence_data = await ai_service.generate_fill_in_sentence(
word.word_original,
learning_lang=learning_lang,
translation_lang=translation_lang
)
# Локализация заголовка
if translation_lang == 'en':
fill_title = "Fill in the blank in the sentence:"
elif translation_lang == 'ja':
fill_title = "文の空欄を埋めてください:"
else:
fill_title = "Заполни пропуск в предложении:"
task = {
'type': 'fill_in',
'word_id': word.id,
'question': (
f"Заполни пропуск в предложении:\n\n"
f"{fill_title}\n\n"
f"<b>{sentence_data['sentence']}</b>\n\n"
f"<i>{sentence_data.get('translation', '')}</i>"
),