Я довольно давно живу в Армении и изучаю армянский язык для получения гражданства (“вы должны уметь читать любой документ” - сказали мне в миграционном центре).
Армянский язык очень сложен, и у меня возникла идея написать приложение для иммерсивного (dove — нырнул, погрузился) чтения на иностранном языке с пословным контекстуальным переводом, которое способно работать с любыми языками, даже с самыми редкими и сложными.
Сегодня я хочу вам рассказать о том, что у меня получилось - о проекте Language Dove, над которым я работаю уже полгода.
Описание приложения
Чтобы «уметь читать любой документ», нужно много читать. При чтении на иностранном языке мы постоянно спотыкаемся о незнакомые слова и выражения. Основная идея приложения — как можно лучше объяснить пользователю их смысл, чтобы он мог читать и понимать текст, одновременно пополняя словарный запас.
Ядром приложения является алгоритм, который берет текст и создает.html‑файл для иммерсивного чтения.
Поддерживаются следующие фичи:
Пословный контекстуальный перевод — при наведении на слово отображается его перевод в контексте (на тачскрине — клик по слову)
Параллельный перевод предложений — после каждого предложения есть специальная иконка, при наведении на нее показывается перевод всего предложения (на тачскрине — клик по иконке)
Интерактивный словарь — по клику на слово в отдельной вкладке открывается релевантная статья в Wiktionary (на тачскрине — долгий клик по слову)
Озвучка — при правом клике по слову проигрывается его произношение (на тачскине — двойной клик по слову)
Я собрал мультиязычную библиотеку текстов из public domain и обработал их своим алгоритмом.

Библиотека включает:
Сказки Андерсена и братьев Гримм
Басни Эзопа
Фрагменты из Библии
Сербские народные сказки
На данный момент в библиотеке 1205 пар текст‑перевод общей длиной около 3 600 000 символов.
Веб‑приложение предоставляет доступ к этой библиотеке: можно искать по языку оригинала и перевода, названию и автору. Пока тексты в выдаче сортируются просто по убыванию длины текста.
Для кого это приложение:
Для изучающих какой‑то конкретный язык
Для любителей лингвистики в целом
Для тех, кому интересно прочесть какие‑то конкретные важные для них тексты в оригинале
Пословный контекстуальный перевод
Эта фича — душа всего приложения.
Обычно в языковых приложениях просто даются варианты перевода отдельных слов «в вакууме», и это приводит к следующим проблемам:
У слова может быть несколько значений, и тогда приходится гадать, какое имеется в виду. Когда таких слов несколько, происходит комбинаторный взрыв
В языках разная грамматика. Иногда бывает так, что знаешь каждое отдельное слово, а в единый смысл они не складываются
Существуют устойчивые сочетания слов, где смысл выражения нельзя вывести из отдельных составляющих. Примеры: фразовые глаголы в германских языках, сочетания вроде «всё ещё» или «потому что», идиомы
Задача состоит в том, чтобы найти перевод для каждого слова в контексте. При этом, можно объединять несколько подряд идущих слов (чтобы правильно обрабатывать устойчивые сочетания).
Критерии качества:
Перевод слов должен быть как можно более точным по смыслу
Перевод должен быть как можно более понятным читающему: слова должны быть в правильных грамматических формах на языке перевода. Если объединить переводы в цельный текст, он должен звучать как можно более складно
Нужно минимизировать количество объединений соседних слов — в идеале, должны быть объединены только устойчивые выражения
Я решил задачу вручную для небольшого количества данных, и вывел численные метрики для каждого из критериев качества. Таким образом, я могу сравнивать вывод разных алгоритмов с идеалом и по метрикам судить, какой из них объективно лучше.
Для решения задачи я реализовал сложный комбайн из разных LLM‑вызовов и алгоритмической обработки результатов.
Бо́льшая часть разработки всего приложения прошла за улучшением этого сложного комбайна: я анализировал результаты → находил плохие переводы → думал, как модифицировать алгоритм для уменьшения количества ошибок подобного типа → реализовывал изменения → проверял качество по метрикам.
У меня получилось два решения: дорогое и дешевое. Дорогое использует одну из топовых LLM. Дешевое решение дешевле на порядок, и очень ненамного отстает по метрикам — одна из LLM поменьше оказалась очень хороша для этой задачи. При обработке библиотеки я пошел на компромисс с жабой: короткие тексты (меньше 1000 символов) я обрабатываю дорогим решением, а длинные — дешевым.
Давайте проанализируем качество контекстуальных переводов.
Для демонстрации результатов я буду показывать переводы сверху над соответствующими словами.
В самом приложеним есть 3 варианта (можно выбрать в настройках): либо перевод отображается только при наведении, либо пишется сверху и тоже отображается при наведении, либо можно отключить эту функцию. Я лично предпочитаю первый вариант, потому что тогда можно сначала самому попробовать догадаться о смысле незнакомых слов, и только потом смотреть подсказку. При правильной собственной догадке слово лучше запоминается, плюс выделяются эндорфины. Режим со словами наверху нужен для демонстрации работы алгоритма, при конвертации в неинтерактивный формат (картинка, pdf, распечатка) и в будущем для интерактивных субтитров для видео.
Если перевод отображается в фигурных скобках, то это значит, что несколько слов оригинала были объединены вместе.
Сначала испытаем алгоритм на художественном тексте с английского на русский.

Перевод «got» в начале как «подавился» — это очень вольно
«Я сделаю это стоит твоих усилий» — кривая грамматика
«When she cried» — под she имеется в виду журавль, и переведено как «он». Непонятно, волк это или журавль
Теперь возьмем рандомный пост с r/techsupport

Есть проблемы с фразовыми глаголами: «clean it up» нужно было объединить и перевести «почистить его», то же самое касается «took it apart».
«it» в «it doesn»t go» надо было перевести как «температура», «он» звучит совсем непонятно
В «just like a band‑aid fix» слово «like» — это филлер без смысловой нагрузки. Лучший перевод — «типа»
Сможет ли алгоритм понять канцелярит?

«Electors» в контексте американской конституции означает «выборщики», а не «избиратели»
«Branch» в «Branch of the state Legislature» лучше было бы перевести как «Ветвь», а не «Палата», особенно в свете того что текст про Палату Представителей
«являлось семи лет» — надо было вставить «в течение»
«Не лицо» — звучит совсем непонятно. Нужно было написать «Никакое лицо»
Теперь попробуем архаичный текст — Библию короля Якова

Есть небольшая проблема с фразовым глаголом «hath cast more in»: «in» отделилось и было переведено как «в». С другой стороны, объединять целых 4 слова — это тоже не очень.
Вот тот же самый фрагмент в оригинале на древнегреческом

Здесь я не вижу ошибок.
Следующий текст - описание Шрёдингером его мысленного эксперимента с котом

«die man gegen» — правильный перевод слова «man» здесь будет «one»
«aber auch keines» — «aber» здесь значит «or»
Алгоритм здесь немного недокручивает формулировки на английском — можно переводить более складно.

Идем дальше, на очереди латынь, фрагмент из «Commentarii de Bello Gallico» (Записки о Галльской войне) Юлия Цезаря

Проблемы только с недокрученными формулировками на русском:
их языке → на их языке
нашем языке → на нашем языке
все эти → они все
из этих → из них
Что насчет древнерусского? Это фрагмент из «Хождения за три моря» Афанасия Никитина, язык 15-го века

«В том в Чюнере» — «в том» не означает «потом»
«Чюнере» перевено «Chunere», а не «Chuner»
«хоросанецъ» — перевод неправильный, на самом деле у русских купцов это слово означало перса вообще
«воскликнув Махмета» на самом деле означает «притвориться мусульманином»
Теперь пример на армянском

С армянского на русский пословно переводить проще, чем с английского — в армянском очень длинные слова и язык по строю больше похож на русский.
В данном примере я ошибок не вижу.
Короткий пример на китайском — «Теория Кошки» Дэн Сяопина

С китайским языком две проблемы: токенизация (китайцы пишут без пробелов) и сильно отличная грамматика.
В данном примере токенизатор Jieba ошибся 3 раза: не разделил два иероглифа «черная» и «кошка» (потому что «черный кот» в китайском означает еще и полицейского), не разделил два иероглифа «белая» и «кошка» (непонятно почему), разделил иероглифы в сочетании с единым смыслом «ловить» (это что‑то вроде ловить+делать, иероглифы употребляются по отдельности в этих значениях).

Более сложный пример — стихотворение на классическом китайском «История про то, как Ши Ши поедал львов». На пекинском диалекте все слоги читаются как «ши» в одном из четырех тонов.

Несмотря на проблемы с токенизацией, алгоритм в целом справился очень неплохо — по смыслу тут все верно. Когда я показал эту картинку китаянке, ей понравилось.
И наконец, самый сложный язык для алгоритма — японский. Японский еще сложнее китайского — в нем те же самые проблемы с токенизацией и совершенно непривычной грамматикой, только грамматика еще более непривычна.
Вот что получается на тексте из Википедии про игру Го

Японская грамматика ощущается как поток сознания. Есть куда стремиться: можно было этот поток сознания получше на русском отформатировать.
Интерактивный словарь
Смысл этой фичи в том, чтобы новые слова лучше укоренялись в памяти: когда вы встречаете слово в первый раз, очень полезно создать в голове как больше ассоциаций по поводу данного слова, и очень желательно понимать этимологию слова и его связь с другими словами.
Англоязычная Wiktionary подходит для этой цели просто идеально, статьи очень подробные. Они содержат списки значений, таблицы словоизменения, однокоренные слова и этимологию, дополнительную информацию по использованию слов, произношение.
Однако, Wiktionary пополняется пользователями, и количество статей в Wiktionary для определенного языка зависит от количества его носителей. Для редких языков вроде армянского или сербского в Wiktionary будут статьи только для наиболее частотных слов.
Кроме того, часто отсутствуют статьи по отдельным словоформам, есть только по словарным формам слова.
Я скачал дамп Wiktionary для каждого языка, записал в БД список слов, и генерирую ссылку на Wiktionary, если статья для данного слова присутствует; и просто ссылку на Google Translate в противном случае.
Я также придумал способ частично побороть проблему отсутствия статей по словоформам. На основании дампа Wiktionary я вычисляю морфологические паттерны в языке (как из словоформы получить словарную форму) и пытаюсь применить к слову каждый из них. Иногда при этом я выхожу на слово, которое есть в Wiktionary.
Существует еще одна проблема: я всегда использую Wiktionary на английском, потому что там больше всего информации. Однако для тех, кто учит английский с нуля, словарные статьи на английском будут бесполезны. Я планирую через некоторое время перейти на статьи на языках перевода, если язык оригинала английский (хотя бы для самых частотных слов). В теории, можно вообще перевести все статьи на все языки, и даже сгенерировать статьи на те слова, которых нет в Wiktionary (через RAG), но это дорого.
Озвучка
Для озвучки я пока что использую Web Speech API браузера: если в браузере есть хотя бы один голос для данного языка, то при клике на слово проигрывается аудио. И по количеству, и по качеству голосов выигрывает (неожиданно) MS Edge — поэтому если для вас важна эта функция, лучше открывать в нем.
Вынужден предупредить: не стоит использовать функцию озвучки, если в изучаемом языке много омографов (русский, японский, арабский): произношение слов часто будет неправильным.
Развитие проекта
В будущем я планирую добавить следующие фичи
Специальные книги — языковые курсы с нуля. Курс будет представлять собой длинный оптимизированный список предложений, которые подаются в порядке возрастания сложности и снижения частотности лексики
Возможность автоматически обработать кастомный текст алгоритмом, для чего также нужно настроить прием платежей на сайте. На данный момент я принимаю заказы на обработку алгоритмом книг в ручном формате
Добавить в библиотеку видео с YouTube — вместо.html‑файла c текстом будет открываться.html‑плеер с видео и интерактивными субтитрами
Возможность автоматически обработать кастомное видео алгоритмом
Флеш‑карточки с употреблением слова в контексте
Также, я буду продолжать работать над улучшением качества контекстуальных переводов и постепенно добавлять в библиотеку новые материалы.
Итак, после 6 месяцев разработки я, наконец‑то, решился представить свое творение на суд людской: https://languagedove.com. Буду рад фидбеку!
Комментарии (7)
Maciej
17.07.2025 14:06Японская грамматика постпозиционная, поэтому надо дожидаться конца предложения. Возможно, с тюрксими языками будут подобные проблемы.
einhorn Автор
17.07.2025 14:06Кстати, у меня алгоритм учитывает, что она постпозиционная
Он объединяет стандартные послелоги с предшествующими токенами - на практике это дает приличный буст к качеству, даже несмотря на увеличение количества объединений
То же самое с турецким, но там пока только со словом için такое делается (надо будет побольше послелогов прописать)
apayrus
Очень интересно.
Мне понравился формат пословного перевода над оригинальным текстам. Кажется, не видел такого раньше. Удобно.
einhorn Автор
Я видел такое пару раз, но сделанное вручную
ru1z
Наверное японцам ближе, у них фуригана часто используется (к которой ruby тег) для передачи фонетики.
einhorn Автор
Ага, именно через тег ruby это и сделано
apayrus
теперь вспомнил. несколько лет назад обратил внимание на этот тэг и забыл