Riasss

Riasss

Буратино спрашивает у папы Карло: кто я по национальности? Папа Карло: Ты чурка.
Пикабушник
Дата рождения: 13 сентября
в топе авторов на 527 месте
105 рейтинг 0 подписчиков 4 подписки 1 пост 0 в горячем
Награды:
5 лет на Пикабу

Как я учил польский, сгорел от Google Translate и случайно написал мобильное приложение с ИИ

Привет, Пикабу. Мне 23 года и недавно я решил начать учить польский. Я с детства учу английский, владею им на хорошем уровне и знаю, насколько мне тяжело дается учеба. Просто зубрить слова и правила - это не мое, становится скучно моментально и, что самое главное, не запоминается практически ничего. Основываясь на этом опыте, я понимал, что мне нужно погружение в контекст. Так как польский (также как и русский) относятся к славянским языкам и в них довольно много похожих по звучанию и значению слов, я стал сразу пытаться начать читать.

И тут начались первые проблемы. На сайтах, на которых есть тексты, адаптированные для уровня А1-А2 читалка без встроенного переводчика. Импортировать тексты в Apple Books это совсем не то и неудобно. Я начал искать альтернативы.

Приложение, которое мне понравилось по функционалу, - это LingQ. У него есть встроенная библиотека текстов, перевод слов по тапу, карточки и, казалось бы, вот он, идеальный вариант. И это он, если бы не цена в 13 фунтов ежемесячно. На хобби тратить столько денег на подписку я посчитал не целесообразно.

Помимо изучения языков, я увлекаюсь программированием на пайтон и вайбкодингом.

Так и родился LinguaVibe.

Что вообще получилось

LinguaVibe - это Flutter-приложение для чтения иностранных текстов. Сейчас поддерживает 5 языков: польский, испанский, немецкий, французский и английский. Интерфейс - на русском.

Основная фича: ты вставляешь текст (или импортируешь статью по URL), читаешь, и когда встречаешь незнакомое слово - тапаешь на него. Приложение отправляет всё предложение в LLaMA через Groq API и получает перевод с учётом контекста. Не просто «слово → перевод», а полноценный разбор: начальная форма, перевод, грамматика и даже пример предложения.

Вторая по важности фича: ты можешь вставить свой ключ Groq API, который получается совершенно бесплатно и получить практически весь функционал приложения совершенно бесплатно, с условием, что у вас установлено приложение с названием из 3 букв.

После этого сохраняешь слово в словарь, а потом учишь его через встроенные карточки с системой интервального повторения (SRS, метод Лейтнера).

Главное меню приложения

Главное меню приложения

Стек и архитектура

Тут всё просто, без enterprise-булщита:

Фронтенд (мобилка):

- Flutter (Dart) - потому что кроссплатформа и горячая перезагрузка

- Provider - стейт-менеджмент, без Riverpod-магии

- Isar - локальная NoSQL база. Быстрая, асинхронная, и главное - у меня отдельная база на каждый язык (`isar_pl`, `isar_es` и т.д.)

- flutter_tts - озвучка слов. Польский, испанский, немецкий - всё произносит

Бэкенд:

- Node.js + Express - лёгкий сервер на соседнем репозитории

- Docker - контейнеризация, потому что я не хочу настраивать сервер руками в 3 часа ночи

- Caddy - reverse proxy с автоматическими HTTPS-сертификатами. Lets Encrypt сам всё делает, красота

AI:

- Groq API - LLaMA 3.1 8B для быстрых переводов по тапу, LLaMA 3.3 70B для генерации примеров и переводов заголовков. Groq быстрый - ответы за 200-300мс, это важно когда ты тапаешь на слова в тексте

Словарь

Словарь

Как я это кодил

Буду честен - я вайб-кодил с ИИ-помощниками. Opencode, Cursor, Claude - всё было. Я Python-разработчик, Dart я до этого практически не трогал. Но с ИИ-ассистентами это оказалось не так страшно.

Архитектуру продумал сам: сервисы, репозитории, провайдеры. А детали реализации  делал с ИИ. Это реально работает, если ты понимаешь что хочешь получить.

Вот так выглядит перевод по тапу

Вот так выглядит перевод по тапу

Грабли, на которые я наступил (и закрыл)

Вот тут самое интересное для технарей. Перед релизом пришлось закрывать несколько серьёзных дыр.

1. APP_SECRET_KEY в коде

Изначально ключ бэкенда был захардкожен в `server_config.dart`. Это ужасно - любой может декомпилировать APK и получить ключ.

Решение: перенёс ключ в `--dart-define=APP_SECRET_KEY` при билде. Ключ хранится в `.env` файле (который в `.gitignore`), а билд-скрипт подставляет его через `dart-define`. В коде - `const String.fromEnvironment('APP_SECRET_KEY')`. При декомпиляции ключ не найти в plaintext.

2. SSRF-атаки в веб-парсере

У меня есть фича импорта текстов по URL. Пользователь вставляет ссылку, приложение парсит статью и вытаскивает текст. Проблема: если пользователь вставит `http://localhost:3000/admin` или `http://169.254.169.254/latest/meta-data/` (AWS metadata)?

Решение: в `WebParserService` добавил валидацию URL:

- Проверяю что схема - только `http` или `https`

- Блокирую localhost, 127.0.0.1

- Блокирую приватные сети (10.x.x.x, 172.16-31.x.x, 192.168.x.x)

- Блокирую AWS/GCP metadata (`169.254.169.254`)

// Блокируем SSRF

if (uri.isLoopback || uri.isPrivate) throw Exception('Blocked');

if (uri.host == '169.254.169.254') throw Exception('Blocked');

3. Накрутка лимитов

У меня freemium-модель: бесплатно 10 переводов в день и 3 импорта URL. Premium - безлимит. Но что если пользователь будет спамить запросы?

Решение: на бэкенде - rate limiting по userId. На клиенте - счётчики в SharedPreferences с ежедневным сбросом. Перед каждым запросом - проверка лимита. Если превышен - кидается `SubscriptionTranslationLimitException` и показывается диалог с предложением купить Premium.

4. Вебхуки ЮКассы и идемпотентность

Для Android-оплаты использую ЮКассу. Бэкенд создаёт платёж, пользователь оплачивает в WebView, ЮКасса шлёт вебхук. Проблема: вебхук может прийти дважды (сеть моргнула, таймаут, retry).

Решение: на бэкенде - идемпотентная обработка вебхуков. Каждый платёж имеет уникальный ID, и если вебхук уже обработан - повторный игнорируется. Плюс проверка HMAC-подписи от ЮКассы, чтобы никто не мог подделать вебхук.

5. WebView для платежей

На Android оплата идёт через WebView с ЮКассой. Нужно было убедиться, что пользователь не уйдёт со страницы оплаты и что deep link сработает корректно.

Решение: `webview_flutter` с `NavigationDelegate`. Разрешаю навигацию только на домены `yookassa.ru` и `yandex.ru`. Ловлю deep link `linguavibe://payment-success` через `onNavigationRequest` и `onUrlChange` - как только редирект на наш scheme, закрываем WebView и обновляем статус Premium.

Самый сок в том, что все эти уязвимости (включая защиту от SSRF в парсере и дыру в WebView) мне подсветил не платный аудит и не Claude, а бесплатный Qwen 3.6 в OpenCode, когда я ради прикола скинул ему структуру проекта и спросил: „Где я тут обосрался?“. Нейронка буквально ткнула меня носом в безопасность, расписала, что у меня не так и предложила фиксы.

Читалка

Читалка

Что умеет приложение сейчас

Чтение:

- Вставка текста вручную

- Импорт статьи по URL (парсинг с фильтрацией мусора - рекламы, privacy policy и прочего)

- Тап на слово → AI-перевод с контекстом

- TTS-озвучка каждого слова

Словарь:

- Все сохранённые слова с поиском

- Ручное добавление слов (с AI-генерацией перевода и примера)

- Редактирование переводов

Карточки (SRS):

- Метод Лейтнера: 6 коробок с интервалами 5 мин → 4 ч → 1 день → 3 дня → 7 дней → 14 дней

- 3D-анимация переворота карточки

- Настраиваемый лимит слов за сессию (10-100)

- Слова на 5-й коробке считаются освоенными

Настройки:

- Groq API ключ (вставил свой кюч - тогда безлимит)

- Темы: светлая, тёмная, системная

- Стиль плиток: градиент или монохром

- Экспорт/импорт словаря в JSON (Premium)

- Серия дней (streak) - мотивация не бросать

Premium:

- iOS: In-App Purchase, 449 ₽/мес

- Android: ЮКасса, 349 ₽/мес

- Безлимитные переводы и импорты

- Если вставишь свой Groq API ключ - лимиты снимаются и без подписки

Бонус: приложение весит всего 20 МБ в RuStore. Оптимизировал сборку, убрал лишнее, и получилось довольно компактно для Flutter-приложения.

Карточки с интервальным повторением

Карточки с интервальным повторением

Где скачать и потестить

На данный момент приложение доступно только в RuStore под Android. В будущем планируется релиз под iOS в AppStore.

👉 RuStore

👉 Сайт проекта

Буду рад любому фидбеку - кидайте в комменты что сломалось, что бесит, чего не хватает. Особенно интересно мнение тех, кто учит языки через чтение.

P.S. Да, я всё ещё учу польский. Да, приложение реально помогает. Нет, я не бросил. Do zobaczenia! 🇵🇱

Показать полностью 5
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества