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

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

be8c1c462f3e1c90330c2280fe2612fe.gif

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

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

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

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

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

dadb081624052030530daea8c0947bac.jpgТекст ответа

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

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

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

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

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

9af5f6e56b7c1c57db2dbeec9e93744b.gifРазметка демо-страницы



    
        
        Пользовательский виджет yatranslate для сайта на чистом js
        

        
        
        
        

    

    

        

        

Автоматический перевод сайта

Перевод сайта на другие языки при помощи виджета "Яндекс.Переводчик для сайтов"

Пример настраиваемого виджета

Hello World!!!

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


Содержимое 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 = `${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

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

© Habrahabr.ru