Я довольно давно живу в Армении и изучаю армянский язык для получения гражданства (“вы должны уметь читать любой документ” - сказали мне в миграционном центре). 

Армянский язык очень сложен, и у меня возникла идея написать приложение для иммерсивного (dove — нырнул, погрузился) чтения на иностранном языке с пословным контекстуальным переводом, которое способно работать с любыми языками, даже с самыми редкими и сложными.

Сегодня я хочу вам рассказать о том, что у меня получилось - о проекте Language Dove, над которым я работаю уже полгода.

Описание приложения

Чтобы «уметь читать любой документ», нужно много читать. При чтении на иностранном языке мы постоянно спотыкаемся о незнакомые слова и выражения. Основная идея приложения — как можно лучше объяснить пользователю их смысл, чтобы он мог читать и понимать текст, одновременно пополняя словарный запас.

Ядром приложения является алгоритм, который берет текст и создает.html‑файл для иммерсивного чтения.

Поддерживаются следующие фичи:

  1. Пословный контекстуальный перевод — при наведении на слово отображается его перевод в контексте (на тачскрине — клик по слову)

  2. Параллельный перевод предложений — после каждого предложения есть специальная иконка, при наведении на нее показывается перевод всего предложения (на тачскрине — клик по иконке)

  3. Интерактивный словарь — по клику на слово в отдельной вкладке открывается релевантная статья в Wiktionary (на тачскрине — долгий клик по слову)

  4. Озвучка — при правом клике по слову проигрывается его произношение (на тачскине — двойной клик по слову)

Я собрал мультиязычную библиотеку текстов из public domain и обработал их своим алгоритмом.

Библиотека включает:

  1. Сказки Андерсена и братьев Гримм

  2. Басни Эзопа

  3. Фрагменты из Библии

  4. Сербские народные сказки

На данный момент в библиотеке 1205 пар текст‑перевод общей длиной около 3 600 000 символов.

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

Для кого это приложение:

  1. Для изучающих какой‑то конкретный язык

  2. Для любителей лингвистики в целом

  3. Для тех, кому интересно прочесть какие‑то конкретные важные для них тексты в оригинале

Пословный контекстуальный перевод

Эта фича — душа всего приложения.

Обычно в языковых приложениях просто даются варианты перевода отдельных слов «в вакууме», и это приводит к следующим проблемам:

  1. У слова может быть несколько значений, и тогда приходится гадать, какое имеется в виду. Когда таких слов несколько, происходит комбинаторный взрыв

  2. В языках разная грамматика. Иногда бывает так, что знаешь каждое отдельное слово, а в единый смысл они не складываются

  3. Существуют устойчивые сочетания слов, где смысл выражения нельзя вывести из отдельных составляющих. Примеры: фразовые глаголы в германских языках, сочетания вроде «всё ещё» или «потому что», идиомы

Задача состоит в том, чтобы найти перевод для каждого слова в контексте. При этом, можно объединять несколько подряд идущих слов (чтобы правильно обрабатывать устойчивые сочетания).

Критерии качества:

  1. Перевод слов должен быть как можно более точным по смыслу

  2. Перевод должен быть как можно более понятным читающему: слова должны быть в правильных грамматических формах на языке перевода. Если объединить переводы в цельный текст, он должен звучать как можно более складно

  3. Нужно минимизировать количество объединений соседних слов — в идеале, должны быть объединены только устойчивые выражения

Я решил задачу вручную для небольшого количества данных, и вывел численные метрики для каждого из критериев качества. Таким образом, я могу сравнивать вывод разных алгоритмов с идеалом и по метрикам судить, какой из них объективно лучше.

Для решения задачи я реализовал сложный комбайн из разных 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 — поэтому если для вас важна эта функция, лучше открывать в нем.

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

Развитие проекта

В будущем я планирую добавить следующие фичи

  1. Специальные книги — языковые курсы с нуля. Курс будет представлять собой длинный оптимизированный список предложений, которые подаются в порядке возрастания сложности и снижения частотности лексики

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

  3. Добавить в библиотеку видео с YouTube — вместо.html‑файла c текстом будет открываться.html‑плеер с видео и интерактивными субтитрами

  4. Возможность автоматически обработать кастомное видео алгоритмом

  5. Флеш‑карточки с употреблением слова в контексте

Также, я буду продолжать работать над улучшением качества контекстуальных переводов и постепенно добавлять в библиотеку новые материалы.

Итак, после 6 месяцев разработки я, наконец‑то, решился представить свое творение на суд людской: https://languagedove.com. Буду рад фидбеку!

Комментарии (7)


  1. apayrus
    17.07.2025 14:06

    Очень интересно.
    Мне понравился формат пословного перевода над оригинальным текстам. Кажется, не видел такого раньше. Удобно.


    1. einhorn Автор
      17.07.2025 14:06

      Я видел такое пару раз, но сделанное вручную


    1. ru1z
      17.07.2025 14:06

      формат пословного перевода над оригинальным текстам

      Наверное японцам ближе, у них фуригана часто используется (к которой ruby тег) для передачи фонетики.


      1. einhorn Автор
        17.07.2025 14:06

        Ага, именно через тег ruby это и сделано


        1. apayrus
          17.07.2025 14:06

          теперь вспомнил. несколько лет назад обратил внимание на этот тэг и забыл


  1. Maciej
    17.07.2025 14:06

    Японская грамматика постпозиционная, поэтому надо дожидаться конца предложения. Возможно, с тюрксими языками будут подобные проблемы.


    1. einhorn Автор
      17.07.2025 14:06

      Кстати, у меня алгоритм учитывает, что она постпозиционная

      Он объединяет стандартные послелоги с предшествующими токенами - на практике это дает приличный буст к качеству, даже несмотря на увеличение количества объединений

      То же самое с турецким, но там пока только со словом için такое делается (надо будет побольше послелогов прописать)