В данной статье весь код написан на JavaScript (с использованием JQuery).
Использование неофициальных API преследуется законом.
Сегодня хочу рассказать о реализации функции перевода текста на веб-страницах. Предстоит решить сразу несколько проблем:
Цена. API как Яндекс.Переводчика, так и Google Translate обходятся недешево, что совершенно не подходит стартап-проектам.
Скорость. Перевод должен осуществляться практически мгновенно, чтобы текст было читать максимально комфортно.
Возврат. Необходимо предоставить пользователю возможность моментально просматривать оригинальный текст.
Легкость. Под легкостью я подразумеваю как минимальную нагрузку на браузер, так и максимально быструю загрузку скрипта.
В первой части статьи описывается решение лишь двух проблем.
Цена
Итак, начнем с цены. Поискав в интернете, оказалось, что раньше практически все API переводчиков были бесплатными, сейчас же у всех есть бесплатный лимит, а далее вовсе не привлекательные цены:
Поискав еще немного, я наткнулся на статью о бесплатном 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). Если информация оказалось полезной, поделитесь ей с друзьями и коллегами!
Подпишитесь на мой телеграм-канал, чтобы не пропустить новый контент!
Комментарии (6)
AlexanderMarginal
01.09.2022 20:08+11. А зачем через api google с фронта, если можно отдавать на фронт уже переведенный контент?
2. Зачем в 2022 вам понадобился jQuery и XMLHttpRequest ?
3. Зачем минифицировать js на каком-то левом сайте который неизвестно что вам по факту отдаст на выходе (в том числе возможно и какого-то зловреда), когда можно использовать для этих целей например webpack?
4. Если у вас не переведен вообще весь контент с бэкэнда, то зачем делать это с помощью Google через какие-то запросы ручные, когда пользователь может просто нажать в контекстном меню браузера кнопку "перевести на свой язык" ?
Bigata
03.09.2022 13:01Всё равно автора следует похвалить автора за попытку. Ну велосипед, ну старые решения, но работает. Может за исключением минимизации кода.
yarkov
А можно узнать зачем это делать в 2022 году?
12rbah
Наверное еще за
XMLHttpRequest() попросят пояснить
povProgramming Автор
Я лишь начинающий программист, в статье описал решение заинтересовавшей меня проблемы. В 2022 году достаточно много людей имеют старое устройство/ПО, которое не имеет встроенный переводчик, из-за чего у меня и возникла идея реализации переводчика на сайте. Во всяком случае спасибо за комментарий, буду исправляться :)
12rbah
Честно говоря, в статье больше рекламы, чем полезной информации.
Если честно то вы почти ничего не пояснили, вы просто показали как сделать запрос к апи через XHR. Если вы пишите про полезный софт, то хотя бы стоит дать ссылку на гитхаб или хотя бы возможность попробовать софт.
Не подумайте, что я сильно критикую, просто смысла в такой статье нет, т.к. она недоработана.
P.S. Если вы не пишите +/- хорошие статьи, то за ссылку на тг могут накидать минусов в карму.