Как стать автором
Обновить

Кастомный виджет Яндекс.Переводчик для сайтов

Время на прочтение 6 мин
Количество просмотров 13K

Когда-то я предложил свое решение по кастомизации виджета googleTranslate, тема оказалась действительно полезной и актуальна по сей день. Репозиторий с проектом на gitHub набрал немного звезд, а я рад тому, что мои труды не напрасны. И вот недавно мне понадобилось сделать пользовательский выпадающий список с выбором языков, но уже с виджетом яндекс переводчика. Вообще сам по себе виджет вполне устраивал заказчика, но проблема заключается в том что в нем по умолчанию находится более 90 языков и этот список нельзя никак ограничить. Нельзя выставить 2-3 или 5 необходимых вам языков, будут показаны все 90+, но проблема еще и в том, что виджет не адаптивен, он занимает 1221 пиксель в ширину и никак не подстраивается под размер экрана:

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

На сайте, где генерируется виджет есть ссылка на документацию, и конечно же я её начал изучить, но документация на самом деле об API и никакой информации по работе с виджетом не имеет. Я решил написать в тех. поддержку яндекса:

Текст обращения

Здравствуйте. Виджет переводчика, ведет на документацию в которой вообще о виджете не слова. В частности, как для виджета выбрать для перевода не весь список из 80 языков, а например 5, которые необходимы. И как используя виджет запретить переводить определенные слова в html разметке. Например гугл виджет для этого использует класс notranslate и все что в нем не будет переведено.

И довольно быстро получил ответ:

Текст ответа

Здравствуйте, Виталий!

Такой возможности в нашем виджете сейчас нет.

Спасибо за желание сделать Яндекс.Переводчик удобнее! Я передал ваше предложение команде разработки.

И теперь окончательно убедившись, что готового решения нет, я принялся за дело.

Как будет выглядеть пример:

Разметка демо-страницы
<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title>Пользовательский виджет yatranslate для сайта на чистом js</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <!-- yatranslate -->
        <script src="./js/yatranslate.js"></script>
        <link rel="stylesheet" href="./css/yatranslate.css">
        <!-- END yatranslate -->

    </head>

    <body class="body">

        <div class="lang lang_fixed">
            <div id="ytWidget" style="display: none;"></div>
            <div class="lang__link lang__link_select" data-lang-active>
                <img class="lang__img lang__img_select" src="./images/lang/lang__ru.png" alt="Ru">
            </div>
            <div class="lang__list" data-lang-list>
                <a class="lang__link lang__link_sub" data-ya-lang="ru">
                    <img class="lang__img" src="./images/lang/lang__ru.png" alt="ru">
                </a>
                <a class="lang__link lang__link_sub" data-ya-lang="en">
                    <img class="lang__img" src="./images/lang/lang__en.png" alt="en">
                </a>
                <a class="lang__link lang__link_sub" data-ya-lang="de">
                    <img class="lang__img" src="./images/lang/lang__de.png" alt="de">
                </a>
                <a class="lang__link lang__link_sub" data-ya-lang="zh">
                    <img class="lang__img" src="./images/lang/lang__zh.png" alt="zh">
                </a>
                <a class="lang__link lang__link_sub" data-ya-lang="fr">
                    <img class="lang__img" src="./images/lang/lang__fr.png" alt="fr">
                </a>
            </div>
        </div>

        <section class="content">
            <h1 class="content__title">Автоматический перевод сайта</h1>
            <div class="content__desc">
                <p>Перевод сайта на другие языки при помощи виджета "Яндекс.Переводчик для сайтов"</p>
                <p>Пример настраиваемого виджета</p>
                <p>Hello World!!!</p>
            </div>
        </section>

        <style>
            /* Стили для демонстрации */
            /* Styles for demonstration */
            body {
                display: flex;
                justify-content: center;
                align-items: center;
                min-height: 100vh;
                margin: 0;
                padding: 0;
                font-family: tahoma;
            }

            .content {
                text-align: center;
                margin: auto;
            }

        </style>
    </body>

</html>

Для корректной работы виджета необходимо подключить файлы:

<script src="./js/yatranslate.js"></script>
<link rel="stylesheet" href="./css/yatranslate.css">
Содержимое yatranslate.css
/* lang */

.lang {
    position: relative;
    z-index: 10;
    text-align: center;
    background: rgba(157, 157, 157, 0.3);
    perspective: 700px;
}

.lang_fixed {
    position: fixed;
    right: 20px;
    top: 20px;
}

.lang__link {
    cursor: pointer;
    transition: .3s all;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    flex-shrink: 0;
    box-sizing: border-box;
    text-decoration: none;
    border-radius: 2px;
    padding: 4px;
}

.lang__img {
    width: 30px;
    height: 18px;
    flex-shrink: 0;
    font-size: 10px;
    display: block;
    transition: .3s all;
}

.lang__link_sub:hover {
    filter: drop-shadow(0 0 3px rgb(136, 136, 136)) brightness(130%);
}


.lang__name {
    color: #737b84;
    font-size: 12px;
    line-height: 12px;
    flex-shrink: 0;
    text-transform: uppercase;
}

.lang__link_sub {
    width: 100%;
    height: auto;
    position: relative;
    padding: 0;
    margin-bottom: 2px;
}

.lang__list {
    background: rgba(157, 157, 157, 0.3);
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    width: 100%;
    opacity: 0;
    visibility: hidden;
    transition: .3s all;
    transform: rotateX(-90deg);
    position: absolute;
    left: 0;
    top: 100%;
    z-index: 10;
    line-height: 13px;
    padding: 4px;
    transform-origin: center top;
    box-sizing: border-box;
}

.lang:hover .lang__list {
    opacity: 1;
    visibility: visible;
    transform: rotateX(0);
}

.lang__link_select {
    align-items: flex-start;
    text-align: center;
    font-size: 0;
}
Содержимое yatranslate.js
/*!***************************************************
 * yatranslate.js v1.0.0
 * author: Vitalii P.
 *****************************************************/

const yatranslate = {
    /* Original language */
    lang: "ru",
    /* The language we translate into on the first visit */
    /* Язык, на который переводим при первом посещении */
    // langFirstVisit: 'en',
};

document.addEventListener('DOMContentLoaded', function () {
    // Start
    yaTranslateInit();
})

function yaTranslateInit() {

    if (yatranslate.langFirstVisit && !localStorage.getItem('yt-widget')) {
        /* Если установлен язык перевода для первого посещения и в localStorage нет yt-widget */
        /* If the translation language is installed for the first visit and in localStorage no yt-widget */
        yaTranslateSetLang(yatranslate.langFirstVisit);
    }

    // Подключаем виджет yandex translate
    // Connecting the yandex translate widget
    let script = document.createElement('script');
    script.src = `https://translate.yandex.net/website-widget/v1/widget.js?widgetId=ytWidget&pageLang=${yatranslate.lang}&widgetTheme=light&autoMode=false`;
    document.getElementsByTagName('head')[0].appendChild(script);

    // Получаем и записываем язык на который переводим
    // We get and write down the language into which we translate
    let code = yaTranslateGetCode();

    // Показываем текущий язык в меню
    // Show the current language in the menu
    yaTranslateHtmlHandler(code);

    // Вешаем событие клик на флаги
    // We hang the event click on the flags
    yaTranslateEventHandler('click', '[data-ya-lang]', function (el) {
        yaTranslateSetLang(el.getAttribute('data-ya-lang'));
        // Перезагружаем страницу
        // Reloading the page
        window.location.reload();
    })
}

function yaTranslateSetLang(lang) {
    // Записываем выбранный язык в localStorage объект yt-widget 
    // Writing the selected language to localStorage 
    localStorage.setItem('yt-widget', JSON.stringify({
        "lang": lang,
        "active": true
    }));
}

function yaTranslateGetCode() {
    // Возвращаем язык на который переводим
    // Returning the language to which we are translating
    return (localStorage["yt-widget"] != undefined && JSON.parse(localStorage["yt-widget"]).lang != undefined) ? JSON.parse(localStorage["yt-widget"]).lang : yatranslate.lang;
}

function yaTranslateHtmlHandler(code) {
    // Получаем язык на который переводим и производим необходимые манипуляции с DOM
    // We get the language to which we translate and produce the necessary manipulations with DOM 
    document.querySelector('[data-lang-active]').innerHTML = `<img class="lang__img lang__img_select" src="./images/lang/lang__${code}.png" alt="${code}">`;
    document.querySelector(`[data-ya-lang="${code}"]`).remove();
}

function yaTranslateEventHandler(event, selector, handler) {
    document.addEventListener(event, function (e) {
        let el = e.target.closest(selector);
        if (el) handler(el);
    });
}
Используемые флаги

Логика виджета довольно простая. При выборе языка в локальное хранилище записывается объект с ключем yt-widget. В объекте хранится язык на который будет переведен сайт:

{
	"lang":"en",
	"active":true
}

К локальному хранилищу без проблем можно получить доступ и я применил ту же технику что и с гугл переводчиком. Виджет яндекса прячем, а кликая на свой кастоный флажок с атрибутом data-ya-lang назначаем записаный в нем язык свойству lang и перезагружаем страницу. После перезагрузки страницы язык, который мы сами установили, будет подхвачен виджетом и сайт будет на него переведен. В функции yaTranslateHtmlHandler проводим необходимые манипуляции с разметкой, в моем случае я показываю флаг текущего языка перевода и удаляю его из общего списка. В js каждый этап я разбил на функции и добавил описание, чтобы было легче доработать код под себя.

Репозиторий с проектом на GitHub

Демонстрация

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
+6
Комментарии 1
Комментарии Комментарии 1

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн