В этой статье я расскажу и покажу как с помощью API переводить текст в своем приложении, используя язык программирования С #.
Во время разработки приложения для поиска объявлений, я столкнулся с тем, что необходимо было внедрить функцию – выбор пользователем интересующего города или иного населенного пункта России. Проблема заключалась в том, что в базах данных, с которыми приложение должно взаимодействовать, все города записаны на латинице, и никаких других единых идентификаторов нет. Так как список населенных пунктов России весьма крупный – статически присваивать им англоязычное название было слишком трудоемкой задачей. Поэтому я решил внедрить в приложение автоматический переводчик, который воспринимал бы города, введенные пользователем на русском языке, и выдавал латинский вариант написания города, который соответствовал значению в базах данных.
API (Application Programming Interface), предоставляемое Яндексом, состоит из различных инструментов, которые позволяют использовать сервис в своих целях. API сервиса Яндекс.Переводчика позволяет переводить слова в своих приложениях. Его я и использовал.
Разберем на примере:
- Необходимо получить API-ключ сервиса Яндекс.Переводчик. Для этого нужно зарегистрировать аккаунт на Яндекс. Ключ создается по простому нажатию кнопки.
2. Ключ представляет собой набор символов (зачеркнут).
3. Создадим проект простого приложения в Visual Studio C #. Импортируем необходимые библиотеки.
4. Создадим форму с двумя полями ввода и кнопкой.
5. Код двух классов для перевода
Здесь переменная request содержит строку для подключения к сервису перевода. Она состоит из адреса сервиса, API-ключа (зачеркнут), текста для перевода, и языка перевода. Запрос отправляется на сервер, после чего мы получаем ответ в переменной response. Ответ представляет собой структуру в формате JSON, поэтому необходимо ее конвертировать обратно. Для этого создан класс Translation, в переменной text которого будет содержаться переведенный текст.
6. Вызываем написанный код при нажатии на кнопку формы.
7. Результат
В итоге, мы создали приложение, которое связывается с сервисом Яндекс.Переводчик и может переводить любой введенный текст на выбранный язык.
Помню, как еще в школе на Basic я писал программу-переводчик. И это было то время, когда ты сам составлял словарь, зашивал перевод каждого слова, а затем разбивал строки на слова и переводил каждое слово в отдельности. В то время я, конечно же, не мог и представить, как сильно продвинутся технологии, и программы-переводчики станут в основе использовать механизмы глубокого обучения с архитектурой трансформера и блоками внимания.
В это раз я решил окунуться немного в прошлое и сделать то, что хорошо сделать тогда у меня не получилось.
В современных задачах системы перевода нужны достаточно часто, а специалисту, занимающемуся машинным обучением, возможно чаще, чем в других видах деятельности. Потребность в переводчике стала мне необходима, и я решил прибегнуть к использованию облачных решений, в частности Google Translate.
Я программирую на python, и в python есть отличная библиотека translators. Данная библиотека позволяет использовать множество различных сервисов по переводу. Причем абсолютно бесплатно. Однако, все же данное решение не идеально по нескольким причинам:
-
Перевод выполняется достаточно долго.
-
При большом количестве запросов, переводчик начинает пропускать предложения, т.е. оставляет их в непереведенном виде. Причем никаких ошибок при этом не выводится.
-
Качество перевода не самое высокое, как я это проверял, я расскажу в своей статье ниже.
Конечно же, не стоит изобретать велосипед, поэтому я стал использовать отличное готовое решение Argos Translate. Это open-source бесплатное решение для машинного перевода. Поддерживается огромное количество языков. Может работать в разных режимах: и как десктоп приложение, и как веб приложение, и как библиотека к python.
Автор сам обучает и совершенствует модели для различных языков, однако мне нужна была модель по переводу с английского на русский язык, но данная модель в этой программе не достаточно хороша и никем не поддерживается. Поэтому я решил поддержать проект и взяться за обучение модели перевода с английского на русский язык, чтобы существенно повысить качество перевода имеющейся модели.
Автор проекта Argos Translate поставляет свой скрипт обучения, доступный всем желающим. Для обучения своей модели я взял его за основу, однако в процессе несколько его видоизменил. Далее я покажу основные составляющие процесса обучения модели машинного перевода и разобью их на составные части для лучшего понимания.
Этап 1: Подготовка данных для обучения
Для обучения модели машинного перевода необходимо большое количество параллельных корпусов текстов, к счастью, в сети есть очень большое количество параллельных корпусов текста, за основу я взял датасеты с сайта https://opus.nlpl.eu/
В качестве данных для обучения я использовал список корпусов текстов: ada83.en-ru, bible-uedin.en-ru, Books.en-ru, CCMatrix.en-ru, ELRC_2922.en-ru, EUbookshop.en-ru, GlobalVoices.en-ru, GNOME.en-ru, infopankki.en-ru, KDE4.en-ru, MultiUN.en-ru, News-Commentary.en-ru, OpenSubtitles.en-ru, ParaCrawl.en-ru, PHP.en-ru, QED.en-ru, Tanzil.en-ru, Tatoeba.en-ru, TED2013.en-ru, TED2020.en-ru, tico-19.en-ru, TildeMODEL.en-ru, Ubuntu.en-ru, UN.en-ru, WikiMatrix.en-ru, wikimedia.en-ru, WMT-News.en-ru
В общем итоге у меня получилось собрать тренировочный корпус размером более 80 млн пар предложений.
Для последующей тренировки все данные нам необходимо собрать в файлы:
-
src-train.txt — все исходные предложения на русском языке,
-
tgt-train.txt — все переводы предложений на английском языке,
-
all.txt — все предложения корпуса на двух языках, данный файл необходим для генерации общего словаря,
-
src-val.txt — 2000 предложений для валидации,
-
tgt-val.txt — 2000 переводов предложений для валидации.
Этап 2: Генерация словаря токенов
В качестве основного движка модели используется библиотека нейронного машинного перевода OpenNMT-py с открытым исходным кодом на pytorch.
Библиотека для тренировки использует yml конфигурационные файлы, в которых описываются параметры тренировки модели.
Я использовал стандартный конфиг из репозитория argos-train: https://github.com/argosopentech/argos-train/blob/master/config.yml
В моделях перевода argos translate используется общий словарь для обоих языков.
Для генерации словаря, используется следующий скрипт, в нем берутся первые 10 млн случайных предложений из корпуса, и генерируется из них словарь размером в 50 тысяч токенов.
#!/bin/bash
spm_train --input=run/split_data/all.txt --model_prefix=run/sentencepiece --vocab_size=50000 --character_coverage=0.9995 --input_sentence_size=10000000 --shuffle_input_sentence=true --split_digits
В качестве генерации словаря используется очень популярный токенизатор SentencePiece, который использует в качестве словаря наиболее частотные единицы подслов.
Для перевода модели токенизатора SentencePiece в словарь модели используется команда:
#!/bin/bash
onmt_build_vocab -config config.yml -n_sample -1
и часть конфига отвечающая за формирование словаря:
#config.yml
## Where the samples will be written
save_data: run/opennmt_data
## Where the vocab(s) will be written
src_vocab: run/opennmt_data/openmt.vocab
tgt_vocab: run/opennmt_data/openmt.vocab
# Should match the vocab size for SentencePiece
# https://forum.opennmt.net/t/opennmt-py-error-when-training-with-large-amount-of-data/4310/12?u=argosopentech
src_vocab_size: 50000
tgt_vocab_size: 50000
share_vocab: True
# Corpus opts:
data:
corpus_1:
path_src: run/split_data/src-train.txt
path_tgt: run/split_data/tgt-train.txt
transforms: [sentencepiece, filtertoolong]
valid:
path_src: run/split_data/src-val.txt
path_tgt: run/split_data/tgt-val.txt
transforms: [sentencepiece, filtertoolong]
### Transform related opts:
#### https://opennmt.net/OpenNMT-py/FAQ.html#how-do-i-use-the-transformer-model
#### Subword
src_subword_model: run/sentencepiece.model
tgt_subword_model: run/sentencepiece.model
src_subword_nbest: 1
src_subword_alpha: 0.0
tgt_subword_nbest: 1
tgt_subword_alpha: 0.0
#### Filter
src_seq_length: 150
tgt_seq_length: 150
Этап 3: Тренировка модели
В качестве архитектуры обучаемой модели используется архитектура трансформера, состоящая из кодировщика и декодировщика, каждый размером 6 слоев. 8 голов самовнимания. Размером эмбединга – 512, и размером скрытого связующего состояния между кодировщиком и декодировщиком – 2048.
#config.yml
# Model
encoder_type: transformer
decoder_type: transformer
position_encoding: true
enc_layers: 6
dec_layers: 6
heads: 8
rnn_size: 512
word_vec_size: 512
transformer_ff: 2048
dropout_steps: [0]
dropout: [0.1]
attention_dropout: [0.1]
В качестве оптимизатора используется Adam, в начале обучения в течение первых 8000 шагов используется прогрев модели, с последующим снижением скорости обучения.
Для запуска процесса обучения используется команда:
#!/bin/bash
onmt_train -config config.yml
Обучение моей модели длилось 100 000 шагов и в общем случае занимает от 2 до 5 дней, в зависимости от конфигурации оборудования.
Этап 4: Тестирование качества модели
После обучения нам необходимо проверить, насколько хорошо переводит наша модель.
Для оценки качества модели я использовал отдельный параллельный корпус «Yandex Translate corpus 1m version 1.3» размером в 1 млн пар предложений, в качестве метрики я использовал метрику BLEU Score.
Я использовал следующий скрипт для тестирования модели
#!/bin/bash
#тестирование модели по метрике BLEU
#https://opennmt.net/OpenNMT-py/examples/Translation.html?highlight=bleu
echo "Step 001 Токенизируем наш корпус тестирования"
spm_encode --model=run/sentencepiece.model
< argos-train/csv/test_crps/src-test.txt
> argos-train/csv/test_crps/src-test.txt.sp
spm_encode --model=run/sentencepiece.model
< argos-train/csv/test_crps/tgt-test.txt
> argos-train/csv/test_crps/tgt-test.txt.sp
echo "Step 002 Переведем наш корпус с помощью модели"
for checkpoint in run/openmt.model_step*.pt; do
echo "# Translating with checkpoint $checkpoint"
base=$(basename $checkpoint)
onmt_translate
-gpu 0
-batch_size 8192 -batch_type tokens
-beam_size 5
-model $checkpoint
-src argos-train/csv/test_crps/src-test.txt.sp
-tgt argos-train/csv/test_crps/tgt-test.txt.sp
-output run/wmt/test.ru.hyp_${base%.*}.sp
done
echo "Step 003 Декодируем перевод из токенов обратно в текст"
for checkpoint in run/openmt.model_step*.pt; do
base=$(basename $checkpoint)
spm_decode
-model=run/sentencepiece.model
-input_format=piece
< run/wmt/test.ru.hyp_${base%.*}.sp
> run/wmt/test.ru.hyp_${base%.*}
done
echo "Step 004 Сравним два корпуса по оценке BLEU Score"
for checkpoint in run/openmt.model_step*.pt; do
echo "$checkpoint"
base=$(basename $checkpoint)
sacrebleu argos-train/csv/test_crps/tgt-test.txt < run/wmt/test.ru.hyp_${base%.*}
done
echo "Step End"
По итогам обучения моя модель получила метрику BLEU: 21.6
Для сравнения с другим переводчиком, я перевел 1 млн предложений из тестового корпуса Yandex через библиотеку translators, переводчиком Google Translate.
Отдельно сравнил качество с помощью команды:
#!/bin/bash
sacrebleu argos-train/csv/test_crps/tgt-test.txt < argos-train/csv/test_crps/tgt-test_google.txt
В итоге получил метрику BLEU Score полученного перевода бесплатного Google переводчика BLEU: 18.7
Что означает, что полученная мною модель переводит с русского на английский лучше, чем бесплатный Google Translate.
Этап 5: Упаковываем модель в Argos Translate
Для упаковки модели в формат Argos Translate, необходимо выполнить ряд преобразований.
-
Конвертация модели из checkpoint:
#!/bin/bash ./../OpenNMT-py/tools/average_models.py -m run/openmt.model_step_100000.pt run/openmt.model_step_100000.pt -o run/averaged.pt
-
Квантизация модели:
#!/bin/bash
ct2-opennmt-py-converter --model_path run/averaged.pt --output_dir run/model --quantization int8
-
Конвертация модели в формат argos translate:
#!/usr/bin/env python3 from pathlib import Path import json import subprocess import shutil import sys import argostrain from argostrain.dataset import * from argostrain import data from argostrain import opennmtutils from argostrain import settings import stanza from_code = input("From code (ISO 639): ") to_code = input("To code (ISO 639): ") from_name = input("From name: ") to_name = input("To name: ") version = input("Version: ") package_version = version argos_version = "1.5" package_version_code = package_version.replace(".", "_") model_dir = f"translate-{from_code}_{to_code}-{package_version_code}" model_path = Path("run") / model_dir subprocess.run(["mkdir", model_path]) subprocess.run(["cp", "-r", "run/model", model_path]) subprocess.run(["cp", "run/sentencepiece.model", model_path]) # Include a Stanza sentence boundary detection model stanza_model_located = False stanza_lang_code = from_code while not stanza_model_located: try: stanza.download(stanza_lang_code, dir="run/stanza", processors="tokenize") stanza_model_located = True except: print(f"Could not locate stanza model for lang {stanza_lang_code}") print( "Enter the code of a different language to attempt to use its stanza model." ) print( "This will work best for with a similar language to the one you are attempting to translate." ) print( "This will require manually editing the Stanza package in the finished model to change its code" ) stanza_lang_code = input("Stanza language code (ISO 639): ") subprocess.run(["cp", "-r", "run/stanza", model_path]) subprocess.run(["cp", "run/metadata.json", model_path]) subprocess.run(["cp", "run/README.md", model_path]) package_path = ( Path("run") / f"translate-{from_code}_{to_code}-{package_version_code}.argosmodel" ) shutil.make_archive(model_dir, "zip", root_dir="run", base_dir=model_dir) subprocess.run(["mv", model_dir + ".zip", package_path]) # Make .argoscheckpoint zip latest_checkpoint = opennmtutils.get_checkpoints()[-1] print(latest_checkpoint) print(latest_checkpoint.name) print(latest_checkpoint.num) print(f"Package saved to {str(package_path.resolve())}")
Далее мы получаем готовую модель файла в виде «translate-en_ru-1_7.argosmodel», которую можно подгрузить и использовать в продукте Argos Translate.
В качестве заключения
В рамках данной статьи я показал, что обучить свою модель машинного перевода, которая переводит лучше, чем бесплатный Google Translate, не так уж и сложно, и под силу практически каждому.
Кроме того, я показал, что существуют бесплатные продукты вроде Argos Translate, с помощью которых можно переводить тексты, не прибегая к облачным вычислителям.
Так как продукт Argos Translate является бесплатным, то я поделился с сообществом своей обученной моделью в комьюнити продукта. Разработчики Argos Translate приняли мою модель Russian — English и включили в основной репозиторий моделей машинного перевода в качестве основной модели под версией 1.7.
Если у вас есть идеи, как еще можно улучшить качество перевода данной модели, пишите их в комментариях, и мы вместе сможем еще сильнее улучшить данную модель!
Эксперт по Машинному обучению в IT-компании Lad.
В рамках этого урока создадим приложение переводчик на kotlin в Android studio. Приложение будет предельно простым и состоять из поля EditText для ввода текста, кнопки “Translate” и поля TextView для вывода перевода. Язык введённого текса будет определятся автоматически переводчиком, а язык выводимого текста будет определятся “локалью” приложения, т. е. языком ввода на устройстве. Для приложения будет нужно разрешение на интернет в манифесте, т.к. перевод получается по средствам интернет сервиса.
Напишем Translater на Android Studio на языке kotlin
Первое что мы сделаем это создадим новый пакет (pakage) translater. В этом пакете будем хранить файлы переводчика, чтобы в будущих проектах не ломая голову копировать весь пакет и применить переводчик, например для локализации базы данных приложения на все языки.
В пакете translate создадим два файла:
- Language – этот файл будет хранить все языки
- TranslateAPI – тут находится
Файл Language
package ru.jandroid.translate2.translate object Language { const val AUTO_DETECT = "auto" const val AFRIKAANS = "af" const val ALBANIAN = "sq" const val ARABIC = "ar" const val ARMENIAN = "hy" const val AZERBAIJANI = "az" const val BASQUE = "eu" const val BELARUSIAN = "be" const val BENGALI = "bn" const val BULGARIAN = "bg" const val CATALAN = "ca" const val CHINESE = "zh-CN" const val CROATIAN = "hr" const val CZECH = "cs" const val DANISH = "da" const val DUTCH = "nl" const val ENGLISH = "en" const val ESTONIAN = "et" const val FILIPINO = "tl" const val FINNISH = "fi" const val FRENCH = "fr" const val GALICIAN = "gl" const val GEORGIAN = "ka" const val GERMAN = "de" const val GREEK = "el" const val GUJARATI = "gu" const val HAITIAN_CREOLE = "ht" const val HEBREW = "iw" const val HINDI = "hi" const val HUNGARIAN = "hu" const val ICELANDIC = "is" const val INDONESIAN = "id" const val IRISH = "ga" const val ITALIAN = "it" const val JAPANESE = "ja" const val KANNADA = "kn" const val KOREAN = "ko" const val LATIN = "la" const val LATVIAN = "lv" const val LITHUANIAN = "lt" const val MACEDONIAN = "mk" const val MALAY = "ms" const val MALTESE = "mt" const val NORWEGIAN = "no" const val PERSIAN = "fa" const val POLISH = "pl" const val PORTUGUESE = "pt" const val ROMANIAN = "ro" const val RUSSIAN = "ru" const val SERBIAN = "sr" const val SLOVAK = "sk" const val SLOVENIAN = "sl" const val SPANISH = "es" const val SWAHILI = "sw" const val SWEDISH = "sv" const val TAMIL = "ta" const val TELUGU = "te" const val THAI = "th" const val TURKISH = "tr" const val UKRAINIAN = "uk" const val URDU = "ur" const val VIETNAMESE = "vi" const val WELSH = "cy" const val YIDDISH = "yi" const val CHINESE_SIMPLIFIED = "zh-CN" const val CHINESE_TRADITIONAL = "zh-TW" }
Не забудьте заменить package на свой, иначе ничего работать не будет.
Насчет этого файла объяснять особо нечего. Это набор констант с названиями языков, которые в себе содержат краткое обозначение языка. По сути этот файл сделан для удобства, чтобы не гадать что es – Испанский, а sw – Шведский и т. д.
Файл TranslateAPI
package ru.jandroid.translate2.translate import android.content.ContentValues import android.os.AsyncTask import android.util.Log import org.json.JSONArray import org.json.JSONException import java.io.BufferedReader import java.io.IOException import java.io.InputStreamReader import java.io.UnsupportedEncodingException import java.net.HttpURLConnection import java.net.MalformedURLException import java.net.URL import java.net.URLEncoder class TranslateAPI(langFrom: String?, langTo: String?, text: String?) { var resp: String? = null var url: String? = null var langFrom: String? = null var langTo: String? = null var word: String? = null private var listener: TranslateListener? = null internal inner class Async : AsyncTask<String?, String?, String?>() { override fun doInBackground(vararg params: String?): String? { try { url = "https://translate.googleapis.com/translate_a/single?" + "client=gtx&" + "sl=" + langFrom + "&tl=" + langTo + "&dt=t&q=" + URLEncoder.encode( word, "UTF-8" ) val obj = URL(url) val con = obj.openConnection() as HttpURLConnection con.setRequestProperty("User-Agent", "Mozilla/5.0") val `in` = BufferedReader(InputStreamReader(con.inputStream)) var inputLine: String? val response = StringBuffer() while (`in`.readLine().also { inputLine = it } != null) { response.append(inputLine) } `in`.close() resp = response.toString() } catch (e: UnsupportedEncodingException) { e.printStackTrace() } catch (e: MalformedURLException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } catch (e: Exception) { e.printStackTrace() } return null } override fun onPostExecute(s: String?) { var temp = "" if (resp == null) { listener!!.onFailure("Network Error") } else { try { val main = JSONArray(resp) val total = main[0] as JSONArray for (i in 0 until total.length()) { val currentLine = total[i] as JSONArray temp = temp + currentLine[0].toString() } Log.d(ContentValues.TAG, "onPostExecute: $temp") if (temp.length > 2) { listener!!.onSuccess(temp) } else { listener!!.onFailure("Invalid Input String") } } catch (e: JSONException) { listener!!.onFailure(e.localizedMessage) e.printStackTrace() } } super.onPostExecute(s) } } fun setTranslateListener(listener: TranslateListener?) { this.listener = listener } interface TranslateListener { fun onSuccess(translatedText: String?) fun onFailure(ErrorText: String?) } init { this.langFrom = langFrom this.langTo = langTo word = text val async: Async = Async() async.execute() } }
Это основной файл, который обеспечивает наше приложение переводом.
Функция doInBackground выполняется вне основного потока и обращается к URL https://translate.googleapis.com/. . . , отправляя langFrom (исходный язык текста который нужно перевести) и langTo (язык на который нужно осуществить перевод) и word (текста который нужно перевести) и исходную кодировку UTF-8.
Функция onPostExecute получает в ответ на предыдущий запрос ответ в виде файла JSON.
И посредствам слушателей, написанных в interface TranslateListener, нас оповещают о том что перевод готов и мы можем его использовать, или сообщается об ошибке.
Вкратце это все, что нужно знать об этом файле. По сути вы вообще можете не задумываться о том как этот файл работает, вам главное знать как им пользоваться, а это мы разберём в MainActivity.
Файл activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <EditText android:id="@+id/editText" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="32dp" android:layout_marginEnd="32dp" android:ems="10" android:inputType="textMultiLine|textPersonName" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/btTranslate" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="Translate" app:layout_constraintEnd_toEndOf="@+id/editText" app:layout_constraintStart_toStartOf="@+id/editText" app:layout_constraintTop_toBottomOf="@+id/editText" /> <TextView android:id="@+id/textView" android:layout_width="0dp" android:layout_height="200dp" android:layout_marginTop="16dp" app:layout_constraintEnd_toEndOf="@+id/editText" app:layout_constraintStart_toStartOf="@+id/editText" app:layout_constraintTop_toBottomOf="@+id/btTranslate" /> </androidx.constraintlayout.widget.ConstraintLayout>
Создадим файл разметки интерфейса Layout.
Файл build.gradle (module)
Добавим View Binding в наш проект следующим образом.
buildTypes { ... // Это ViewBinding buildFeatures{ viewBinding true } ...
Файл MainActivity
Вот мы и перешли к основному файлу, с помощью которого мы и научимся пользоваться пакетом нашим translate.
package ru.jandroid.translate2 import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import ru.jandroid.translate2.databinding.ActivityMainBinding import ru.jandroid.translate2.translate.Language import ru.jandroid.translate2.translate.TranslateAPI import java.util.* class MainActivity : AppCompatActivity() { lateinit var binding : ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) binding.btTranslate.setOnClickListener { val countryMy = Locale.getDefault().language.lowercase() val text = binding.editText.getText().toString() val translateAPI = TranslateAPI(Language.AUTO_DETECT, countryMy, text) translateAPI.setTranslateListener(object : TranslateAPI.TranslateListener { override fun onSuccess(translatedText: String?) { binding.textView.text = translatedText } override fun onFailure(ErrorText: String?) { Log.d("MyLog", "Error of translate!") } }) } } }
Не забудьте заменить package на ваш, иначе работать ничего не будет. Про подключения binding я говорить ничего не буду, это тема другого урока.
Наше внимание будет приковано к слушателю кнопки btTranclate. Переменная countryMy получает язык локали, т.е. текущий язык на устройстве. Переменная text получает текст из EditText. TranslateAPI обращается к ранее созданному нами классу TranslateAPI для перевода текста text, язык этого текста Language.AUTO_DETECT (определяется автоматически), countryMy язык нашей локали (язык на устройстве). Все теперь запрос на перевод отправлен.
translateAPI.setTranslateListener . . . { } – это слушатель перевода. Мы не можем сразу получить перевод, т.к. нужно время на отправку запроса на сервер и время на ответ от сервера. По этому нужен слушатель, чтобы мы как можно быстрее узнали, что перевод готов.
Как только перевод будет готов функция onSuccess сообщит нам об этом и мы передаем наш перевод в TextView для отображения строкой binding.textView.text = translatedText.
Если в процессе перевода произошла ошибка то функция onFailure сообщит нам об этом и мы выведем сообщение об ошибке Log.d(“MyLog”, “Error of translate!”).
Заключение
Вот и все. По сути я должен был вам написать так: скопируйте все файлы, и не думайте как они работают, а вот о файле MainActivity мы поговорим, потому, что вам нужно знать лишь как пользоваться пакетом translate. Я думаю, вы согласитесь что это просто.
По сути приложение переводчик абсолютно бесполезно, т.к. есть много таких приложений от серьезных брендов, таких как Yandex или Google и т.д., но польза от него есть. Если вы захотите сделать свое приложение мультиязычным, вы конечно же переведете свой интерфейс по средствам перевода файла strings.xml стандартными функциями Android Studio, но что вы будите делать с данными и базы данных или из внешних файлов? Сделаете в базе данных кучу полей под все языки, это конечно круто, но очень трудоемко. А вот воспользоваться переводчиком очень неплохое решение, и если перевод не удался показать английский вариант. Можно даже при первом запуске приложения сделать полный перевод на язык лакали всех данных из базы данных и потом интернет для перевода будет не нужен.
Если вам понравилась статья, подписывайтесь на наши социальные сети.
Время прочтения: 3 мин.
Крупные компании вносят большой вклад в развитие инфраструктуры интернета. Они предоставляют доступ к своим сервисам и позволяют сторонним разработчикам использовать их. Существует множество таких сервисов (https://yandex.ru/dev/). Сегодня я расскажу про сервис Яндекс.Переводчик и как получить к нему доступ, используя API на примере с использованием языка C#.
Цель подключения сервиса через API:
Во время разработки приложения для поиска объявлений, я столкнулся с тем, что необходимо было внедрить функцию – выбор пользователем интересующего города или иного населенного пункта России. Проблема заключалась в том, что в базах данных, с которыми приложение должно взаимодействовать, все города записаны на латинице, и никаких других единых идентификаторов нет. Так как список населенных пунктов России весьма крупный – статически присваивать им англоязычное название было слишком трудоемкой задачей. Поэтому я решил внедрить в приложение автоматический переводчик, который воспринимал бы города, введенные пользователем на русском языке, и выдавал латинский вариант написания города, который соответствовал значению в базах данных.
API (Application Programming Interface), предоставляемое Яндексом, состоит из различных инструментов,
которые позволяют использовать сервис в своих целях. API сервиса
Яндекс.Переводчика позволяет переводить слова в своих приложениях.
Разберем на примере:
- Необходимо получить API-ключ сервиса Яндекс.Переводчик. Для этого нужно зарегистрировать аккаунт на Яндекс и перейти по ссылке. Ключ создается по простому нажатию кнопки.
2. Ключ представляет собой набор символов (зачеркнут).
3. Создадим проект простого приложения в Visual Studio C#. Импортируем необходимые библиотеки.
4. Создадим форму с двумя полями ввода и кнопкой.
5. Код двух классов для перевода
Здесь переменная request содержит строку для подключения к сервису перевода. Она состоит из адреса сервиса, API-ключа (зачеркнут), текста для перевода, и языка перевода. Запрос отправляется на сервер, после чего мы получаем ответ в переменной response. Ответ представляет собой структуру в формате JSON, поэтому необходимо ее конвертировать обратно. Для этого создан класс Translation, в переменной text которого будет содержаться переведенный текст.
6. Вызываем написанный код при нажатии на кнопку формы.
7. Результат
В итоге, мы создали приложение, которое связывается с сервисом Яндекс.Переводчик и может переводить любой введенный текст на выбранный язык.
Сегодня мы с тобой напишем свой собственный переводчик. Сам функционал перевода мы, конечно же, реализовывать не будем, а обратимся к всемогущему Google, в частности, к Google API Translate. Также немного поковыряем связывание данных в WPF и немного коснемся библиотеки Json.NET, в результате чего у нас получиться свой собственный переводчик. Вперед!
Схема работы
Итак, прежде чем приступать к самому интересному (написанию кода, конечно же
) надо сначала набросать небольшой план работ. Предлагаю разбить весь процесс на следующие этапы:
1.
Разобраться с взаимодействием Google API Translate.
2.
Спроектировать WPF приложение.
3.
Написать код на C# для взаимодействия с Google.
4.
Реализовать связь интерфейса WPF приложения с кодом на C#.
Google API Translate
Итак, сначала нам надо разобраться с тем, как мы будем взаимодействовать с переводчиком от google, так как именно его услугами мы будем пользоваться для непосредственного перевода текста. Небольшие поиски в самом же google подскажут, что для перевода строки текста нам надо послать запрос по такому адресу.
<a href="http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=">http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=</a>[текст для перевода]&langpair=[направление перевода]
Это так называемый REST-запрос, самый просто способ для работы с разного рода API различных веб-сервисов. Например, с теми же вконтакте, твитером можно работать с помощью REST.
В результате Google вернет нам следующий ответ:
{"responseData": {"translatedText":"[Переведенный текст]"}, "responseDetails": null, "responseStatus": [статус перевода]}
Это строка в формате JSON (произносится “джейсан”, насколько я знаю). Нам в нашей программе надо будет только отпарсить этот ответ и выдать результат перевода пользователю. Для того чтобы приложение могло разбирать ответы в виде JSON-строки, нам понадобится библиотека Json.NET. Слить ее можно отсюда:
http://json.codeplex.com
. Есть и другие библиотеки, но я остановился на этой. В принципе, в нашем случае можно было бы обойтись и регулярными выражениями, но для расширения кругозора я предлагаю попробовать Json.NET.
ПРОЕКТИРОВАНИЕ WPF-ПРИЛОЖЕНИЯ
Теперь разберемся, как будет выглядеть и работать наше WPF-приложение. Я предлагаю особо не заморачиваться и сделать простой интерфейс с двумя TextBlock’ами, TextBox’ами и одной кнопкой. Мой вариант на рисунке 1.
Рис. 1
Но хочу тебе напомнить, чтобы мы имеем дело с WPF, а потому, ты можешь сделать по-настоящему красивый дизинг, все ограничивается твоей фантазией. Моей, как видишь, хватило не намного
Основной функционал, а именно перевод текста предлагаю возложить на отдельный класс. Это нам позволит максимально разделить движок и интерфейс, а также облегчит нам процедуру связывания данных, о которой мы поговорим чуть позже.
Класс будет содержать три закрытых метода:
• Stream GetHttpStream(string url).Получаем поток данных с сайта с адресом url.
• String ConvertStreamTostring(Stream stmSource).Преобразуем полученный поток stmSource в строку.
• void GetTranslateDirection ().Определяем направление перевода, т.е. язык, с которого будем переводить. Делать это будет элементарным анализов первых нескольких символов.
Кстати, первые два метода из примеров программ на C# под названием “101 C# Samples”. Поковыряй на досуге, много интересного
.
Затем нам понадобятся 4 закрытых объекта:
• объект типа HttpWebResponse, который будет содержать ответ от сервера google для его последующего анализа;
• логическая переменная, определяющая направление перевода bEnRus. Наш переводчик будет переводить только в 2-х направлениях: с английского на русский и обратно. Поэтому хватит одной переменной для определения направления перевода. Значение данной переменной, кстати, мы и будем устанавливать в описанном выше методе GetTranslateDirection().
• Оригинальный текст для перевода strOriginal;
• переведенный текст strResult;
После обернем последние два поля в свойства, чтобы можно было из вне ими управлять, и определим самую главную функцию Translate,которая и будет осуществлять переводы. Эта функция будет открытой, доступной из всей сборки.
Теперь немного поговорим о связывании данных. Благодаря этому механизму, мы можем связывать элементы управления и объекты данных. В данном случае мы будем связывать элементы TextBox нашей формы с полями класса ClassTranslator. Для этого надо указать в параметре Text (это для примера, можно и другие параметры связывать) нужного TextBox’а свойство нашего класса. Теперь значение этого свойства будет определять значение параметра Text. И когда это свойство будет в классе меняться, свойство Text нашего элемента также будет меняться. Для того чтобы это делалось автоматически (изменение свойства вызывало изменение параметра), наш класс должен реализовать интерфейс INotifyPropertyChanged. Он уведомляет приемники данных (которыми и являются наши TextBox’ы) об изменении значения свойств. У него только 1 метод: PropertyChanged.
В результате у нас должен получиться такой каркас класса:
class ClassTranslator: INotifyPropertyChanged { String strOriginal; String strResult; Boolean bEnRus; HttpWebResponse wresScrape; /// <summary> /// Преобразуем поток данных в строку /// </summary> /// <param name="stmSource">Поток данных</param> /// <returns>Возвращаем строку</returns> private string ConvertStreamTostring(Stream stmSource) { } /// <summary> /// Получаем поток данных от севрера, /// адрес которого указан в параметре /// </summary> /// <param name="url">Адрес,содержащий запрос /// к серверу Google /// </param> /// <returns>Возвращаем поток данных, /// полученных в ответ /// </returns> private Stream GetHttpStream(string url) { } #region Properties /// <summary> /// Свойство-обертка для поля /// strOriginal /// </summary> public string Original { ///устанавливаем значение ///и информируем о изменении свойства set {strOriginal = value; OnPropertyChanged("Original");} get {return strOriginal;} } /// <summary> /// Свойство-обертка для поля /// strOriginal /// </summary> public string Result { get { return strResult;} } #endregion /// <summary> /// Определяем направление перевода /// </summary> private void GetTranslateDirection() { } /// <summary> /// ГЛАВНАЯ-Функция,выполняющая перевод /// </summary> public void Translate() { } /// <summary> /// указатель на событие PropertyChanged /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// Функция,которая будет вызываться /// при изменении нужных нам свойств /// </summary> /// <param name="strPropertyName">Имя сво-ва,котрое поменялось</param> protected void OnPropertyChanged(string strPropertyName) { } }
Погружаемся в код
Начинаем потихоньку реализовывать наш класс. Сперва, разберемся с 3 закрытыми методами. Как я уже сказал, первые два взяты из “101 C# Samples”,так что я просто приведу их листинги с небольшими комментариями.
/// <summary> /// Получаем поток данных от севрера, /// адрес которого указан в параметре /// </summary> private Stream GetHttpStream(string url) { ///Создаем объект для запроса к серверу HttpWebRequest wreqScrape = (HttpWebRequest)(WebRequest.Create(url)); ///заполняем необходимые поля wreqScrape.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.1)"; wreqScrape.Method = "GET"; wreqScrape.Timeout = 10000; try { ///возвращаем поток данных, ///полученных от сервера wresScrape = (HttpWebResponse)(wreqScrape.GetResponse()); return wresScrape.GetResponseStream(); } catch { ///формируем объект исключение с текстом ошибки ///и возвращаем вызывающей функции throw new Exception("There was an error retrieving the Web page " + "you requested. Please check the Url and your connection to " + "the Internet, and try again."); } }
/// <summary> /// Преобразуем поток данных в строку /// </summary> private string ConvertStreamTostring(Stream stmSource) { ///Объявляем обект,который будем использовать ///для чтения из потока StreamReader sr = null; ///если поток-источник не пуст if (stmSource != null) { ///предпринимаем попытку ///считать данные try { ///загружаем поток в StreamReader sr = new StreamReader(stmSource); ///считываем поток до конца ///и возвращаем результат return sr.ReadToEnd(); } catch { ///ничего не сообщаем об ошибке ///просто генерируем новое исключение ///для вызывающего кода throw new Exception(); } finally { ///при любом раскладе закрываем ///закрываем объект-ответ от сайта wresScrape.Close(); ///и поток-читатель sr.Close(); } } else { return null; } }
Теперь рассмотрим функцию определения языка оригинального текста GetTranslateLang().Нам главное определить язык, С КОТОРОГО будем переводить. Раз у нас переводчик поддерживает только 2 языка, то, определив язык оригинала, мы автоматически определим и язык, на который надо переводить. Я предлагаю просто просмотреть первые 5 символов (причем, именно буквенные, не пробелы, цифры и т.д.), а потом проанализировать, символы, какого алфавита встречались чаще. Вот как это выглядит в коде.
/// <summary> /// Определяем направление перевода /// </summary> private void GetTranslateDirection() { ///переменная,содержащая кол-во ///встретившихся русских символов Byte bRus=0; ///переменная,содержащая кол-во ///встретившихся английских символов Byte bEn = 0; ///определяем кол-во необходимых символом ///алфавита для определения принадлежности ///к данному алфавиту Byte bSuccess = (strOriginal.Length<5)?(Byte)strOriginal.Length:(Byte)5; ///запускаем цикл по строке ///Пояснение:чтобы результат был ///регистронезависимым ///приводим всю строку ///к ВЕРХНЕМУ регистру foreach (char c in strOriginal.ToUpper()) { ///проверяем принадлежность ///символа тому или иному алфавиту if (c >= 'А' && c <= 'Я') bRus++; else if (c >= 'A' && c <= 'Z') bEn++; ///ПРОВЕРКА:найдено ли необходимо количество ///символом того или иного алфавита if (bRus == bSuccess) { bEnRus = false; break; } else if (bEn == bSuccess) { bEnRus = true; break; } } }
Разберем и главную функцию Translate.Суть ее работы проста: она формирует запрос к google-переводчику на основе полей strOriginal и bEnRus, затем получает и анализирует ответ, и записывает результат в переменную strResult.Все это, с комментариями и описано чуть ниже.
/// <summary> /// ГЛАВНАЯ-Функция,выполняющая перевод /// </summary> public void Translate() { ///Определяем направление перевода GetTranslateDirection(); ///начинаем формировать строку ///запроса к серверу-переводчика StringBuilder sb=new StringBuilder(@"http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="); ///добавляем оригинальный текст sb.Append(strOriginal); sb.Append("&langpair="); ///добавляем направление перевода sb.Append((bEnRus)?"en|ru":"ru|en"); ///получаем строку-ответ от сервера strResult = ConvertStreamTostring(GetHttpStream(sb.ToString())); ///преобразуем строку в JSON-объект JObject o = JObject.Parse(strResult); ///записываем результат strResult = o["responseData"].First().First().ToString(); ///извещаем приемник данных ///о изменении свойства OnPropertyChanged("Result"); }
Здесь хочу кое-что дополнительно объяснить. Как ты помнишь, ответ от google нам приходит в таком виде:
{"responseData": {"translatedText":"[Переведенный текст]"}, "responseDetails": null, "responseStatus": [статус перевода]}.
Для того чтобы нам добраться до строки Переведенный текст, нам надо от responseData перейти к его первому потомку. Мы попадем на translatedText, а уже его первым потомком будет как раз Переведенный текст. Поэтому мы и используем
strResult = o["responseData"].First().First().ToString();
Кстати, для использования библиотеки Json.NET надо выполнить следующие действия:
• добавить ссылку на нее, через Project->Add Reference(там нужный файл надо найти через закладку Browse ), после чего ты увидишь ее в списке ссылок;
• подключить нужное пространство имен using Newtonsoft.Json.Linq;
Связывание интерфейса с кодом
Ну вот, мы и подошли к заключительной стадии: связывание программного кода с формой. В принципе, основы связывания данных в WPF я уже обрисовал, тут мы просто посмотрим, как это практически реализуется.
Как ты помнишь, у меня есть 2 TextBox’а, в одном исходный текст, а в другом — переведенный.
Вот их разметка в XAML:
<TextBox Height="212" HorizontalAlignment="Left" Margin="12,32,0,0" Name="textBoxOriginal" VerticalAlignment="Top" Width="234" Grid.ColumnSpan="3" /> <TextBox Height="211" HorizontalAlignment="Right" Margin="0,32,12,0" Name="textBoxResult" VerticalAlignment="Top" Width="238" Grid.Column="2" />
Теперь нам надо связать их свойства Text со свойствами класса ClassTranslate. Делается это элементарно:
<TextBox Text="{Binding Path=Original,UpdateSourceTrigger=PropertyChanged}" … /> <TextBox Text="{Binding Path=Result,UpdateSourceTrigger=PropertyChanged}"…/>
Здесь мы указали в свойстве Path имена свойств, которые выступают источниками связывания и название триггера, который будет срабатывать при обновлении свойств.
В процедуре связывания есть еще один момент, который нам пригодиться — это режим связывания. По умолчанию стоит OneWay, т.е. односторонний. Это означает, что содержимое элемента будет зависеть от свойства класса (источника данных), а вот если мы что-то будем вводить в поле, то на свойство класса это влиять не будет. А нам надо, чтобы при вводе пользователем текста, который надо перевести, этот текст попадал в поле strOriginal нашего класса. Поэтому, при связывании текстового блока с полем класса strOriginal мы будем использовать двустороннее связывание-TwoWay.Итоговый вариант будет выглядеть вот так:
<TextBox Text="{Binding Path=Original, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" …/> <TextBox Text="{Binding Path=Result, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" … />
Дальше. Мы указали поля класса, которые будут выступать в качестве источников, но не указали сам объект данного класса, т.е. ЧЬИ поля то выводить. Для этого мы в форме объявим переменную нашего класса,
ClassTranslator translator
=
new
ClassTranslator
(
)
;
а затем укажем ее в качестве свойства DataContext главной сетки формы. Сделаем это в конструкторе формы
public MainWindow() { InitializeComponent(); MainGrid.DataContext=translator; }
И последний штрих. В коде нажатия на нашу кнопку будем вызывать метод Translate переменной
private void buttonTranslate_Click(object sender, RoutedEventArgs e) { translator.Translate(); }
Не удивляйся, когда после нажатия на кнопку форма будет немного подвисать. Отправление и принятие запроса от веб-сервера –не самое быстрое дело.
Заключение
В данной статье я постарался рассмотреть основы связывания данных в WPF и работу с Json-строками. Тебе судить, как это получилось, но я старался =) . В программе есть много моментов для доработки:
• более глубокий анализ переводимого языка. Можно смотреть не первые 5 символов, а, например, 5 слов.
• Надо помнить, что мы работаем с протоколом HTTP, а он имеет ограничение на длину запроса/ответа. Соответственно, если мы собираемся переводить большой текст, его надо разбить на несколько запросов.
• Можно вывести перевод в отдельный фоновый поток, чтобы пока пользователь набивает текст, делался синхронный перевод (как это сделано в самом Google).
Короче, делов много, но старт у тебя уже есть. Удачи!
Written by: Евгений Шапиро
Скачать исходник
Improve Article
Save Article
Improve Article
Save Article
In this article, we are going to make a sentence translator app with the help of API using JavaScript.
Basic setup: Open VS Code and open a folder from your drive where you want to create this project and give the name Translate-Sentence(folderName). After opening create the following files:
- index.html
- translate.js
- style.css
Project Structure: It should look like this:
HTML File: This is the main index page which is connected to the style.css file for styling and translate.js for the logical operations in the website.
The HTML file contains basically three parts:
- Header
- Main Container: It contains two parts:
- Input Textarea
- Output Textarea
- Footer
index.html
HTML
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
meta
http-equiv
=
"X-UA-Compatible"
content
=
"IE=edge"
>
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1.0"
>
<
link
rel
=
"stylesheet"
href
=
"style.css"
>
<
title
>Document</
title
>
</
head
>
<
body
>
<
nav
class
=
"header"
>Translate It</
nav
>
<
div
class
=
"main"
>
<
div
class
=
"translation-box"
>
<
textarea
id
=
"input-text"
placeholder
=
"Enter the sentence"
>
</
textarea
>
</
div
>
<
button
id
=
"btn-translate"
>Translate</
button
>
<
div
id
=
"translated-box"
>
<
textarea
id
=
"output-text"
placeholder
=
"Here you will se translated text"
>
</
textarea
>
</
div
>
</
div
>
<
footer
class
=
"footer"
>About Us</
footer
>
<
script
src
=
"translate.js"
></
script
>
</
body
>
</
html
>
JavaScript File: This javaScript file takes the id of the button and inputs text and outputs text to a variable.
https://api.funtranslations.com/translate/minion.json
Note: API can be used for 5 calls per hour. By using the above API sentence will be translated to the minion language
The main approach of the logic in javascript is:
- On clicking the button a function clickHandler will be called.
- The clickHandler function takes input from the input Textarea and updates the apiUrl.
- Next, the fetch method is called which converts the inputText to minion language and it is reflected to output TextArea.
Fetch method: Fetch takes the Url as an argument and then returns a promise that resolves the response object and then from that response object the outputText takes the translated content.
translate.js
JavaScript
var
inputText = document.querySelector(
'#input-text'
);
var
outputText = document.querySelector(
'#output-text'
);
var
buttonTranslate = document.querySelector(
'#btn-translate'
);
function
errorHandle(error) {
alert(
'Error occurred'
)
console.log(
"error occurred"
, error);
}
function
clickHandler() {
var
text = inputText.value;
var
updatedUrl = apiUrl +
"?text="
+ text;
fetch(updatedUrl).then(response =>
response.json()).then(json =>
outputText.innerText =
(json.contents.translated)).
catch
(errorHandle);
}
buttonTranslate.addEventListener(
"click"
, clickHandler);
CSS File: This file is responsible for the styling of the HTML page.
style.css
CSS
textarea {
display
:
block
;
margin
:
1
rem;
width
:
70
vw;
height
:
20
vh;
padding
:
1
rem;
box-sizing: border-box;
justify-
content
:
center
;
}
* {
box-sizing: border-box;
}
.header {
font-size
:
50px
;
text-align
:
center
;
background-color
:
#f77e38
;
padding
:
1
rem;
}
#btn-translate {
background-color
:
#f77e38
;
border-radius:
12px
;
height
:
5
vh;
width
:
20
vw;
font-size
:
larger
;
margin-left
:
25
vw;
cursor
:
pointer
;
}
.main {
box-sizing: border-box;
margin-left
:
15
vw;
}
.footer {
font-size
:
40px
;
align-items:
center
;
margin-top
:
8
rem;
height
:
7
rem;
background-color
:
#f77e38
;
text-align
:
center
;
}
Output: Install live server extension in VS Code. Click on Live Server and our App is ready now.
Improve Article
Save Article
Improve Article
Save Article
In this article, we are going to make a sentence translator app with the help of API using JavaScript.
Basic setup: Open VS Code and open a folder from your drive where you want to create this project and give the name Translate-Sentence(folderName). After opening create the following files:
- index.html
- translate.js
- style.css
Project Structure: It should look like this:
HTML File: This is the main index page which is connected to the style.css file for styling and translate.js for the logical operations in the website.
The HTML file contains basically three parts:
- Header
- Main Container: It contains two parts:
- Input Textarea
- Output Textarea
- Footer
index.html
HTML
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
meta
http-equiv
=
"X-UA-Compatible"
content
=
"IE=edge"
>
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1.0"
>
<
link
rel
=
"stylesheet"
href
=
"style.css"
>
<
title
>Document</
title
>
</
head
>
<
body
>
<
nav
class
=
"header"
>Translate It</
nav
>
<
div
class
=
"main"
>
<
div
class
=
"translation-box"
>
<
textarea
id
=
"input-text"
placeholder
=
"Enter the sentence"
>
</
textarea
>
</
div
>
<
button
id
=
"btn-translate"
>Translate</
button
>
<
div
id
=
"translated-box"
>
<
textarea
id
=
"output-text"
placeholder
=
"Here you will se translated text"
>
</
textarea
>
</
div
>
</
div
>
<
footer
class
=
"footer"
>About Us</
footer
>
<
script
src
=
"translate.js"
></
script
>
</
body
>
</
html
>
JavaScript File: This javaScript file takes the id of the button and inputs text and outputs text to a variable.
https://api.funtranslations.com/translate/minion.json
Note: API can be used for 5 calls per hour. By using the above API sentence will be translated to the minion language
The main approach of the logic in javascript is:
- On clicking the button a function clickHandler will be called.
- The clickHandler function takes input from the input Textarea and updates the apiUrl.
- Next, the fetch method is called which converts the inputText to minion language and it is reflected to output TextArea.
Fetch method: Fetch takes the Url as an argument and then returns a promise that resolves the response object and then from that response object the outputText takes the translated content.
translate.js
JavaScript
var
inputText = document.querySelector(
'#input-text'
);
var
outputText = document.querySelector(
'#output-text'
);
var
buttonTranslate = document.querySelector(
'#btn-translate'
);
function
errorHandle(error) {
alert(
'Error occurred'
)
console.log(
"error occurred"
, error);
}
function
clickHandler() {
var
text = inputText.value;
var
updatedUrl = apiUrl +
"?text="
+ text;
fetch(updatedUrl).then(response =>
response.json()).then(json =>
outputText.innerText =
(json.contents.translated)).
catch
(errorHandle);
}
buttonTranslate.addEventListener(
"click"
, clickHandler);
CSS File: This file is responsible for the styling of the HTML page.
style.css
CSS
textarea {
display
:
block
;
margin
:
1
rem;
width
:
70
vw;
height
:
20
vh;
padding
:
1
rem;
box-sizing: border-box;
justify-
content
:
center
;
}
* {
box-sizing: border-box;
}
.header {
font-size
:
50px
;
text-align
:
center
;
background-color
:
#f77e38
;
padding
:
1
rem;
}
#btn-translate {
background-color
:
#f77e38
;
border-radius:
12px
;
height
:
5
vh;
width
:
20
vw;
font-size
:
larger
;
margin-left
:
25
vw;
cursor
:
pointer
;
}
.main {
box-sizing: border-box;
margin-left
:
15
vw;
}
.footer {
font-size
:
40px
;
align-items:
center
;
margin-top
:
8
rem;
height
:
7
rem;
background-color
:
#f77e38
;
text-align
:
center
;
}
Output: Install live server extension in VS Code. Click on Live Server and our App is ready now.