Несколько недель назад я решил составить список интересных проектов на Vue.js, и по этой причине я начал рыться в Интернете в поисках ценных ресурсов. В конце дня я собрал значительный объем знаний о некоторых полезных API. Среди прочего, мне очень понравился Яндекс Переводчик API; он может взять почти любой текст и вернуть его эквивалент на более чем 90 языках.

Немного поигравшись с API (используя Postman), я решил взять свои знания о Vue.js и заключить их в великолепие этого API. Результат? Я собрал веб-приложение-переводчик Vue.js.

Во время проекта я интегрировал аудио функционально, сославшись на ResponsiveVoiceJS CDN и запустив простую функцию.

Вот визуальное отображение завершенного проекта:

Посмотрим, как я это построил.

Требования

Поскольку мы собираемся создавать это приложение с помощью Progressive Javascript Framework Vue.js, перед тем, как продолжить, мы должны убедиться, что у вас установлено несколько вещей:

Также нам понадобятся:

Чтобы создать учетную запись на Яндексе, перейдите сюда:

Чтобы создать бесплатный ключ API, перейдите сюда:

После того, как зависимости установлены и у вас есть ключ, мы готовы приступить к работе!

Создание проекта

Мы будем создавать этот проект с помощью инструмента Vue-CLI, альтернативой может быть ссылка на Vue.js из CDN, и вы можете сделать это, если захотите.

Мы будем использовать шаблон webpack-simple, поскольку его не составит труда разработать.

Возможно, вам потребуется сменить владельца для каталога проекта и запустить некоторые из этих команд от имени пользователя root (используя sudo)

vue init webpack-simple translator

С помощью этой команды вам нужно будет ответить на несколько строк запроса командной строки:

Давайте перейдем в каталог проекта и установим зависимости:

cd translator 
npm install

Создание компонента перевода

Мы создадим ровно один компонент для этого проекта, так как мы не хотим загромождать среду разработки ненужными компонентами. Этот компонент будет содержать два textareas, расположенных рядом; одна будет содержать текст для перевода, а другая - отображать переведенный текст, обе стороны также будут иметь audio функциональность.

Давайте создадим каталог components и файл translate в каталоге src нашего только что установленного проекта.

mkdir -p src/components
cd src/components
touch translate.vue

Этот файл будет содержать весь код для компонента translate.

Написание кода для компонента Translate

Прежде чем мы вообще напишем какой-либо код, давайте подумаем о взаимосвязи между корневым компонентом (App.vue) и дочерним компонентом (translate.vue). Предположим, что основная работа будет выполняться корневым компонентом, поэтому дочерний компонент будет получать реквизиты, регистрировать несколько переменных и emit событий вплоть до корневого компонента при взаимодействии с пользователем.

Теперь, когда мы понимаем, как это будет работать, давайте напишем код в теге script для получения свойств и инициализации переменных.

export default {

  name: 'translate',

  props: {

   AvailableLanguages : {
     type : Object
   },

   ResponseText : {
     type : String
   },

   CurrentLanguage : {
     type : String
   },

   TranslateLanguage : {
     type : String
   }
 },

  data () {
    return {
      Text: '',
      FromLanguage : "English",
      ToLanguage : "French"
    }
  }
}

Давайте проанализируем приведенный выше код сверху вниз, чтобы понять, что происходит:

  1. Во-первых, мы экспортируем default, что позволило бы нам импортировать этот компонент в корневой компонент.
  2. Мы инициализируем переменную name, затем получаем и проверяем некоторые реквизиты, очевидно, эти реквизиты будут исходить от корневого компонента. Вот что они собой представляют и чем занимаются:
  • AvailableLanguages будет содержать объект доступных для перевода языков, возвращенный API Яндекса.
  • ResponseText будет содержать переведенный текст для указанного языка, возвращенный API Яндекса.
  • CurrentLanguage будет кодом для текущего языка, который мы набираем.
  • TranslateLanguage - это код языка, на котором будет выполнен перевод.
  1. Наконец, мы инициализируем переменную Text (это для вводимого текста) пустой строкой. Затем мы инициализируем две другие переменные, FromLanguage и ToLanguage, на «английский» и «французский» соответственно. Это переменные, которые будут содержать полное имя (не код) выбранного языка.

Потрясающий.

Написание MarkUp

Получив props и проинициализировав некоторые переменные в приведенном выше коде, мы должны теперь написать HTML. В основном мы будем связывать textareas с соответствующими переменными данных и запускать события при взаимодействии с пользователем. HTML будет записан в тегах template, чтобы Vue.js знал, что это MarkUp, и отображал его во время выполнения.

<div id="parent_translate">

<div id="input">

<div id="imageholder">

<select v-model="FromLanguage" @change="changeFromLanguage">

<option v-for="(lang, code) in AvailableLanguages" :value="code"> {{ lang }} </option>

</select>

<img @click="translateSpeak" src="../assets/speaker.png">

</div>

<textarea placeholder="Type in something here" v-model="Text"></textarea>

<button @click="submit" id="submit">SUBMIT</button>
</div>

<div id="output">


<div id="imageholder">

<select v-model="ToLanguage" @change="changeToLanguage">

  <option v-for="(lang, code) in AvailableLanguages" :value="code"> {{ lang }} </option>

</select>

<img @click="responseSpeak" src="../assets/speaker.png">

</div>

<textarea placeholder="Your output goes here" disabled v-model="ResponseText"> </textarea>

</div>

</div>

Давайте внимательно посмотрим на функциональность, связанную с этим MarkUp:

Первый тег select привязан к переменной данных FromLanguage с помощью директивы v-model и запускает обработчик событий changeFromLanguage при изменении его значения.

Тег option, вложенный в первый тег select, принимает объект доступных языков (который поступает как свойство из корневого компонента) и просматривает его с помощью директивы v-for. Директива :value привязана к переменной code, поэтому каждый тег опции, созданный во время цикла, имеет свой уникальный code.

Давайте посмотрим еще на MarkUp:

<select v-model="FromLanguage" @change="changeFromLanguage">

<option v-for="(lang, code) in AvailableLanguages" :value="code"> {{ lang }} </option>

</select>

Тег img чуть ниже ранее обсужденного тега select содержит представление изображения для звуковых функций и направляет события щелчка в обработчик событий translateSpeak.

<img @click="translateSpeak" src="../assets/speaker.png">

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

<textarea placeholder="Type in something here" v-model="Text"></textarea>

<button @click="submit" id="submit">SUBMIT</button>

Тег button выполняет единственную функцию; он запускает submit метод всякий раз, когда по нему щелкают.

После этой точки в MarkUp оставшийся код представляет собой просто повторение того, что уже было отображено, без новой логики или функций.

Давайте напишем обработчики событий в объекте methods.

Написание обработчиков событий

Давайте начнем этот раздел с написания обработчиков для полей выбора, они срабатывают всякий раз, когда выбран параметр changed.

changeFromLanguage:function( ev ) {
    let LanguageCode = ev.target.value;
    this.$emit('updateFromLanguage', LanguageCode)
  },

  changeToLanguage:function( ev ) {
    let LanguageCode = ev.target.value;
    this.$emit('updateToLanguage', LanguageCode)
  }

Функция этих двух обработчиков совершенно очевидна. Сначала новая переменная содержит язык code для выбранной опции, а затем это обновление emitted для корневого компонента. Также указаны обработчики в корневом компоненте для обработки этих генерируемых событий.

submit:function( ev ){
    let Word = this.Text
    if ( Word ) {
    this.$emit('translate', Word)
    }
  }

Вышеупомянутый метод отправки вызывается всякий раз, когда нажимается Submit кнопка, и его простая задача - emit событие при передаче набранного текста родительскому компоненту.

Прежде чем мы рассмотрим обработчики событий для звуковых функций, мы должны извлечь библиотеку ResponsiveVoiceJS, потому что мы зависим от нее для звуковых функций, мы можем сделать это, вставив тег script непосредственно перед закрывающим тегом </body> файла index.html. .

<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://fonts.googleapis.com/css?family=Indie+Flower" rel="stylesheet">
    <title>A simple translator application using the Yandex API</title>
    <style>

    body{
      overflow-x: hidden;
      overflow-y: hidden; 
      background: linear-gradient( to right, DodgerBlue, lightblue);
    }

    </style>
  </head>
  <body>
    <div id="app"></div>
    <script src="/dist/build.js"></script>
    <script src='https://code.responsivevoice.org/responsivevoice.js'></script>
  </body>
</html>

Чтобы приложение говорило, нам нужна одна функция из библиотеки ResponsiveVoiceJS:

responsiveVoice.speak()

Мы можем встроить эту функцию в наши обработчики звука и получить что-то вроде этого:

translateSpeak:function(){
    responsiveVoice.speak(this.Text);
  },

  responseSpeak:function(){
    responsiveVoice.speak(this.ResponseText);
  }

Функция speak() принимает текст в одной из двух переменных данных и воспроизводит его.

Включая стили

Наконец, давайте добавим некоторые Styles ограниченные области действия, чтобы все оставалось красивым:

<style scoped>
#parent_translate {
  width: 100%;
  height: 100%;
  display: flex;
  flex-wrap: nowrap;
  flex-direction: row;
}
select {
  padding: 0.2em 0em;
  margin: 0;
  font-family: 'Indie Flower', cursive;
}
#submit {
background: #4ed34c;
padding: 0.7em;
border: none;
border-radius: 1px;
cursor: pointer;
color: black;
}
#input, #output {
  background-color: #f1f1f1;
  width: inherit;
  height: inherit;
  text-align: center;
  font-size: 30px;
  border-radius: 60px;
}
#input {
  margin: 0px 2px 0px 0px;
}
#output {
    margin: 0px 0px 0px 2px;  
}
textarea {
  width: inherit;
  height: 60%;
  margin: 0px;
  padding: 45px 20px;
  box-sizing: border-box;
  outline: none;
  border: none;
  text-align: center;
  font-size: 25px;
  font-family: 'Indie Flower', cursive;
  font-weight: bold;
}
#input > div, #output > div {
  width: inherit;
  height: 20%;
  margin: 0px;
  padding: 0px;
}
#input > div > img, #output > div > img {
 padding: 10px 0px 0px 0px;
 width: 12%;
 height: 60%;
 cursor: pointer;
}
</style>

Это действительно все для translate компонента, скоро все станет более функциональным и более интересным.

Создание корневого компонента

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

После создания учетной записи на Яндексе:

Вы сможете создать бесплатный ключ:

Написание MarkUp

Корневому компоненту не нужно так много MarkUp, поэтому мы напишем только несколько строк, в которые добавим компонент translate в качестве настраиваемого тега:

<div id="app">

<h2>VUE AUDIO TRANSLATOR </h2>

<div id="translate">

<translate v-bind:AvailableLanguages="AvailableLanguages" v-bind:TranslateText="TranslateText" v-bind:ResponseText="ResponseText"  @updateFromLanguage="updateFromLanguage($event)" @updateToLanguage="updateToLanguage($event)" @translate="handleTranslation($event)">
</translate>

</div>

</div>

С пользовательским тегом <translate> происходит два примечательных действия, давайте посмотрим на них:

  1. AvailableLanguages, TranslateText и ResponseText передаются как реквизиты.
  2. @updateFromLanguage, @updateToLanguage и @translate принимаются как отправленные события корневым компонентом из компонента перевода.

Включая стили

Давайте добавим несколько стилей, чтобы пользовательский интерфейс выглядел хорошо:

<style scoped>
#translate {
  height: 45vh;
  max-width: 90%;
  margin: 2.5vh auto;
}
h2 {
  text-align: center;
  font-size: 1.6rem;
  color: black;
  font-weight: bold;
  font-family: 'Indie Flower', cursive;
}
</style>

На этом этапе мы можем запустить приложение с помощью этой команды:

npm run dev

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

Давай сделаем это сейчас.

Написание Javascript

Давайте сделаем три вещи в этом компоненте:

  1. Импортируйте компонент перевода.
  2. Зарегистрируйте компонент
  3. Инициализировать переменные
import translate from './components/translate.vue'

export default {
  name: 'app',

  components: {
    translate : translate
  },

  data () {
    return {
      TranslateText : '',
      ResponseText : '',
      CurrentLanguage : 'en',
      TranslateLanguage : 'fr',
      AvailableLanguages : {}
    }
  }

  }

Подключение к методу жизненного цикла Created ()

Vue.js позволяет нам подключаться к различным методам жизненного цикла компонентов и делать разные вещи для повышения гибкости приложения. Для этого приложения мы хотим отправить GET запрос в API Яндекс Переводчика при создании приложения. Поскольку API Яндекс Переводчика позволяет нам создавать HTTP request для полезной нагрузки JSON поддерживаемых языков вместе с их кодами, мы будем отправлять запрос при каждом создании приложения.

Нам нужен HTTP client для отправки этого запроса, поэтому давайте его получим, хотя есть ряд подходящих альтернатив (vue-resource, Fetch API и т. Д.), Мы будем использовать HTTP client axios на основе Promise.

Давайте добавим axios и небольшую оболочку для интеграции axios в Vue.js:

npm install --save axios vue-axios

Чтобы на самом деле использовать axios и vue-axios, нам нужно импортировать и использовать их в файл src/main.js:

import Vue from 'vue'
import App from './App.vue'

import axios from 'axios'
import VueAxios from 'vue-axios'

Vue.use(VueAxios, axios)

new Vue({
  el: '#app',
  render: h => h(App)
})

Теперь, когда мы настроили axios, мы можем запрашивать объект поддерживаемых языков и их коды при каждом создании приложения:

created(){

  var self = this;

 this.axios.get('https://translate.yandex.net/api/v1.5/tr.json/getLangs?ui=en&key=YOUR_KEY_GOES_HERE')
  .then(function (response) {
    self.AvailableLanguages = response.data.langs;
  })
  .catch(function (error) {
    console.log(error);
  })

  }

После запроса API Яндекс Переводчика response асинхронно передается обратно как Promise, мы немного копаемся в response и обновляем значение объекта AvailableLanguages.

Написание методов Translate и ValidateResponse

Это центральная тема всей статьи, потому что именно здесь происходит фактический перевод текстов и проверка запросов. Здесь мы будем делать три простые вещи:

  1. Запрос к API Яндекс Переводчика с нашим уникальным ключом и текстом для перевода.
  2. Проверка ответа, чтобы убедиться, что текст был переведен правильно или была возвращена ошибка.
  3. Обновление значения переменной данных ResponseText, если код ответа 200, или запись строки ошибки в консоль, если это не так.
translate:function(){

  var self = this;

 this.axios.get('https://translate.yandex.net/api/v1.5/tr.json/translate?key=YOUR_KEY_GOES_HERE&text='+self.TranslateText+'&lang='+self.CurrentLanguage+'-'+self.TranslateLanguage+'&format=plain')
  .then(function (response) {

  self.validateResponse(response);
  })
  .catch(function (error) {
    console.log(error);
  })

  },

  validateResponse:function(response){

        if (response.status === 422) {

            console.log('Could Not Translate Text Please Try Again Later');

        } else if (response.status === 413) {

            console.log('Please Enter A Shorter Text to translate');

        } else if (response.status === 200) { 

           this.ResponseText = response.data.text[0]

        } else {

          console.log('Cannot translate at this moment please try again later');
        }
    }

Это почти вся функция этих методов, давайте посмотрим, как корневой компонент обрабатывает события, генерируемые компонентом translate.

Написание обработчиков событий

Из предыдущего раздела мы знаем, что корневой компонент должен обрабатывать три события, генерируемые компонентом translate:

  • @updateFromLanguage, @updateToLanguage и @translate

Давайте напишем методы для их обработки соответственно:

updateFromLanguage:function( value ){
    this.CurrentLanguage = value;
    this.translate();

Этот обработчик получает значение от компонента translate и обновляет с его помощью значение переменной CurrentLanguage. Затем он вызывает метод translate() для завершения своей работы.

Это метод, который запускается в корневом компоненте всякий раз, когда выбирается новый язык (язык для перевода).

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

updateToLanguage:function( value ){
    this.TranslateLanguage = value;
    this.translate();
  }

Этот метод делает почти то же самое, что и метод выше, с той лишь разницей, что он работает с выбором языка, на который переводится, а не языка, с которого переводится.

Наконец, обратите внимание на метод обработки событий щелчка для кнопки отправки компонента перевода:

handleTranslation:function( value ){
    this.TranslateText = value;
    this.translate();
  }

Этот обработчик просто обновляет переменную TranslateText значением параметра, полученного от компонента перевода, а затем переводит текст, вызывая метод translate().

Запуск приложения

Мы можем запустить приложение с помощью этой команды:

npm run dev

Это должно открыть новое окно в браузере по адресу разработки localhost:8080:

Вот и все! Мы только что создали функциональное приложение для перевода аудио, и оно готово к тестированию.

Создайте приложение

При желании мы можем выполнить сборку для производства с помощью этой команды:

npm run build

Вывод

В этом руководстве мы увидели, как создать простое приложение для перевода аудио на Vue.js. Мы также использовали мощный HTTP-клиент axios для запроса данных в API Яндекс Переводчика.

Мы можем сделать вывод, что Vue.js - очень захватывающий прогрессивный фреймворк для создания множества потрясающих проектов.

Код этого проекта доступен на Github.

Первоначально опубликовано на dev.to.