Переводчик сайтов на JS

от автора

В данной статье весь код написан на JavaScript (с использованием JQuery).

Использование неофициальных API преследуется законом.

Сегодня хочу рассказать о реализации функции перевода текста на веб-страницах. Предстоит решить сразу несколько проблем:

  • Цена. API как Яндекс.Переводчика, так и Google Translate обходятся недешево, что совершенно не подходит стартап-проектам.

  • Скорость. Перевод должен осуществляться практически мгновенно, чтобы текст было читать максимально комфортно.

  • Возврат. Необходимо предоставить пользователю возможность моментально просматривать оригинальный текст.

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

В первой части статьи описывается решение лишь двух проблем.

Цена

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

Google Translate
Google Translate
Яндекс.Переводчик
Яндекс.Переводчик
Bing Translator
Bing Translator

Поискав еще немного, я наткнулся на статью о бесплатном API Google Translate, который используется во встроенном в браузер Chrome переводчике, а также на сайте Google Translate. У этого API лишь два ограничения:

  • Скорость. Если беспрерывно посылать запросы, скорость отклика незначительно снизится.

  • Количество символов. Это ограничение обусловлено браузером, который может отправлять в GET запросе максимум 2048 символов (в некоторых источниках 1756).

Первая проблема незаметна при использовании, а вторая решается обычным разбиением строки, которое можно реализовать с помощью регулярного выражения:

string.match(/.{1,2000}(?=\.)/gi) // string – исходная строка // (?=\.) обозначает, что после строки должна быть точка (в примере я разбиваю текст на предложения) // стоит отметить, что перед отправкой запроса разбиваемую строку стоит обернуть в функцию encodeURI(), которая гарантирует, что вся строка дойдет до сервера

Скорость

Скорость ответа Google API увеличить вряд ли получится, а вот уменьшить задержку между получением ответа и отображением результата можно.

Изначально я планировал взять весь текст, отправить его, дождаться ответа и отобразить его, однако, как оказалось, это занимает около минуты. Такие задержки непозволительны, поэтому пришлось искать другое решение. Его я подсмотрел у других переводчиков: они обрабатывают лишь ту часть текста, которая видна пользователю. И опять-таки вопрос: что насчет реализации?

Суть такова:

  • при скролле запустить событие;

  • проверить, clientRect каких элементов ниже верхней границы видимой области, но выше нижней;

  • перевести данные элементы.

Запускаем событие перевода при скролле с помощью  document.addEventListener('scroll', startTranslating). Затем определяем, какие элементы находятся в поле видимости пользователя:

function isScrolledIntoView(element) {     let pageTop = $(window).scrollTop(); // верхняя граница видимой области   let pageBottom = pageTop + $(window).height(); // нижняя граница видимой области   let elementTop = $(element).offset().top; // верхняя граница элемента   let elementBottom = elementTop + $(element).height(); // нижнаяя граница элемента   return ((elementTop <= pageBottom) && (elementBottom >= pageTop)); // возвращает true, если хоть один край элемента в поле видимости пользователя, в противном случае – false }

После отправляем запрос на сервер Google Translate и обрабатываем его:

let translateUrl = "https://translate.googleapis.com/translate_a/single?format=text&client=gtx&sl=" + sl + "&tl=" + tl + "&dt=t&q=" + originalText; // sl – язык оригинала, tl – язык для перевода, originalText – текст запроса (можно использовать результат string.match(/.{1,2000}(?=\.)/gi)) let translatedText = httpGet(translateUrl); function httpGet(url) {   var xmlHttp = new XMLHttpRequest();   xmlHttp.open("GET", url, false);   xmlHttp.send(null);   return xmlHttp.responseText; }

Осталось только обработать полученный текст… или нет?

Осталось решить лишь две проблемы:

  • Возврат. Необходимо предоставить пользователю возможность моментально просматривать оригинальный текст.

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

Возврат

Здесь решение очевидно: достаточно загрузить исходный код в переменную, а при клике на кнопку «Показать оригинал» (или что-то в таком роде) отобразить его. Хорошей идеей также будет загружать в переменную уже переведенный текст, ведь если пользователь снова захочет перевести сайт, придется заново посылать запросы.

Что же касается повторного перевода одних и тех же элементов, то это фиксится добавлением и последующей проверкой наличия класса, например, translated.

Легкость

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

Решить проблему со скоростью загрузки скрипта можно двумя способами (они не исключают друг друга):

  • Минифицировать код. С помощью инструмента от 10015.io у меня получилось сократить финальную версию кода почти на 40%:

  • Использовать CDN. Как указано в статье на Хабре:

    Ускоряем фронтенд. Когда много запросов к серверу — это хорошо.Вместо подключения к центральному серверу пользователь может подключиться к серверу CDN, который находится ближе. Таким образом, обмен пакетами пройдёт гораздо быстрее. Это особенно хорошо подходит для статических ресурсов, таких как CSS, JavaScript и изображения, поскольку их легко распространять через CDN.

На этом, пожалуй, и закончу. Надеюсь, прояснил решение основных проблем (иногда даже с примерами кода =D). Если информация оказалось полезной, поделитесь ей с друзьями и коллегами!

Подпишитесь на мой телеграм-канал, чтобы не пропустить новый контент!


ссылка на оригинал статьи https://habr.com/ru/post/685900/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *