Pull to refresh

Практическое применение Google AJAX Language API — встраиваем переводчик в свой проект.

Reading time 7 min
Views 4.5K

Приветствую вас, уважаемые читатели! Возможно, несколько нескромно, но позволю себе обьявить, что далее будет самый первый в Рунете обзор и описание практического применения недавно открытого Google AJAX Language API для доступа с приложений на JavaScript к сервису переводов. Везде я видел пока только анонсы и попытки проанализировать, чем же это может обернутся для разработчиков и пользователей, но именно руководства по встраиванию в свой сайт или проект еще не читал, поэтому решил самостоятельно разобраться и написать.

И так, сначала общая информация. Как известно, у компании Google есть сервис переводов, который умеет переводить тексты на более чем десятке языков. Всего пар переводов есть намного больше, но для некоторых языков доступны только переводы на один-два языка, для других, например, английского — на множество. Раньше вы могли использовать этот сервис для переводов веб-страниц на лету, или перевода отдельных слов и предложений в браузере, но вот дистанционный доступ к сервису при помощи AJAX-а — это стало возможно только на днях с открытием соответствующего API и размещения примеров кода.

API включает в себя функции автоматического определения языка исходного текста, и, собственно сам перевод. Поддерживается пока тринадцать разных языков и двадцать девять вариантов перевода. К сожалению, русский поддерживается только в виде пары Russian <> English, то есть, перевод с русского на английский и обратно, а самое большое число переводов конечно же, для английского. Впрочем, обещают в дальнейшем пополнять возможности переводов, так что не отчаивайтесь.

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

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

Так где же и как можно использовать эти возможности? Ну, навскидку, как минимум два варианта — перевод каки-то кратких текстов, например, описания товаров или аннотации статей, и автоматический перевод интерфейса и/или системы подсказок на язык пользователя.

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

Так как не все языки имеют полностью все направления перевода, да и нам не всегда нужны все возможности, сначала мы определим все интересующие нас варианты перевода. Сделаем глобальную переменную trans_var, в которой будет следующий массив:
var trans_var = {"en":[{"code":"zh","lang":"Chinese"},{"code":"fr","lang":"French"},
{"code":"de","lang":"German"},{"code":"ru","lang":"Russian"},
{"code":"es","lang":"Spanish"}
],
"ru":[{"code":"en","lang":"English"}],
"de":[{"code":"en","lang":"English"},{"code":"fr","lang":"French"}],
"zh":[{"code":"en","lang":"English"}]};

Он означает, что у нас исходный текст может быть на английском, русском, немецком и китайском, также мы определили, на какие языки можно переводить каждый вариант исходного текста. Самый большой список для английского. Китайский я здесь упомянул скорее ради теста, там есть несколько его вариантов, поэтому нужно, по идее, учитывать написание (традиционное или упрощенное), но это уже вы сами добавите, если необходимо.

Теперь подойдем к визуальной стороне дела или спроектируем интерфейс. Я решил сделать его следующего вида:



В зависимости от определенного языка текста у нас автоматически формируется список языков для перевода (исходя из определений в trans_var, для каждого из который мы выводим изображение национального флага, а также кнопку отмены (возвращает переведенный текст к исходному виду). Изображения флагов взяты из этого набора, а сами файлы переименованы согласно кодам языков. Кстати, сами коды языков, которые использует Google, вы можете узнать здесь.

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

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

Хотя в API есть своя функция для определения языка, я решил написать над ней небольшую обертку, и вместе с функцией отрисовки интерфейса поместить в одну общую, вызывая которую после загрузки страницы вы все сделаете автоматически — определите язык статьи и сразу выведете нужный интерфейс перевода.

Следует заметить, что определение языка, как и перевод, не происходит мгновенно, ведь нужно отослать данные на сервер и дождаться ответа, поэтому для обработки ответа применяется callback функция, которая передается в API.

Я написал свою обертку — _detect_lang_code, которая принимает имя DOM-элемента, в котором находится текст, нужный для перевода, и ссылку на функцию, которую нужно вызвать после определения языка. В нашем случае такой функцией будет ранее описанная отрисовка интерфейса для перевода. Внутри мы сначала получаем сам текст. Так как никакие сторонние библиотеки не используются, то я получаю его через обычное свойство innerHTML (жаль, что для форматированного текста там будут теги, их нужно вырезать), а если браузер IE, то сразу использую свойство innerText. Далее желательно проверить длину текста и обрезать его — функция определения языка требует гораздо меньше символов, чем ограничение на перевод, поэтому для сокращения трафика можно ограничить строку первыми 50 или 100 символами. Теперь вызываем метод для определения языка — в API он называется google.language.detect и принимает два параметра — строку с текстом и callback-функцию, в нашем случае анонимную, которая разбирает ответ. Здесь маленький нюанс, по сравнению с примерами на официальном сайте. Там после определения языка выводится его название полностью, а нам необходимо только узнать его код, поэтому нас будет интересовать только индекс внутреннего массива google.language.Languages, который и есть код языка (сервер возвращает же полное название языка). Все, присвоим глобальной переменной origin_text_lang полученный код и сразу вызовем функцию отрисовки интерфейса. Для исходного текста на English (код en) мы получим интерфейс, показанный на рисунке выше.

Самим переводом занимается наша же функция translate_text, которая, для универсальности, сразу принимает два параметра — коды языков исходного текста и того, на который переводим. Так как мы генерировали код вызова когда создавали интерфейс, то там уже прописан код для каждого языка, а код исходного у нас хранится в глобальной переменной origin_text_lang, поэтому мы сразу передаем ее (хотя, конечно, можно и упростить пример). Далее, при необходимости, мы можем еще раз проверить допустимость такой пары перевода, и, есл нужно, разбиваем наш текст на блоки кратные 500 символам. Если вы хотите, чтобы перевод вставлялся вместо оригинального текста, то сохраните его в переменной — я использую для этого _tmp_original_text.

Собственно, сам перевод выполняется вызовом функции API google.language.translate, которой передается строка с текстом, код языка оригинала, код языка, на который переводим а также ссылка на callback-функцию, которая выполняется после перевода и обрабатывает результат. Так как библиотека берет на себя все низкоуровневые функции, то мы получаем только объект result, который и содержит возвращенные данные. Проверяем свойство result.translation, если он не равно false, значит перевод успешный и в нем содержится переведенная строка текста. Ура, просто заменяем исходный текст переведенным и все!

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

А теперь, на закуску, одна интересная фишка. Хотите сделать, чтобы ваш интерфейс был также переведен на другой язык? Например, в моем одном проекте есть верхнее меню, которое доступно пользователю после регистрации, и там различные пункты, вроде «сообщения», «помощь», «мои программы» и тому подобные. Конечно, все они сопровождаются пиктограммами, которые максимально близко отображают суть меню, но все же хотелось бы перевод. Очень просто! Сначала вам нужно оформить перевод в виде строки, причем для последующей обработки мы сформируем JSON-строку, массив всех пунктов меню. Что-то вроде этого:

[«мои программы»,«подписки»,«сообщения»,«моя статистика»,«выход»,«домой», «поиск»,«помощь»]

Да-да, если такую строку «скормить» переводчику, то все служебные символы останутся нетронутыми! После перевода на английский мы получим:

[ «my programs», «subscribe», «message», «my statistics», «Exit», «home», «Search», «help»]

Как видите, достаточно точный перевод, чтобы ваши посетители смогли им без особых проблем пользоваться для работы с сайтом. Кстати, для того, чтобы перевести на все языки, необходимо переводить не родной интерфейс (если он русский), а отдельно создать массив с английскими обозначениями, а потом переводить его на любой из поддерживаемых. Этот массив в дальнейшем элементарно превращается в JavaScript обьект или используется через ваш любимый фреймворк, а уже как подменить оригинальные надписи в меню вы сами придумаете, ведь правда?

Ссылки по теме:


P.S. Это кросс-пост из моего личного блога. Оригинал находится здесь.
Tags:
Hubs:
+45
Comments 32
Comments Comments 32

Articles