Программа переводчик на kotlin

В рамках этого урока создадим приложение переводчик на kotlin в Android studio. Приложение будет предельно простым и состоять из поля EditText для ввода текста, кнопки “Translate” и поля TextView для вывода перевода. Язык введённого текса будет определятся автоматически переводчиком, а язык выводимого текста будет определятся “локалью” приложения, т. е. языком ввода на устройстве. Для приложения будет нужно разрешение на интернет в манифесте, т.к. перевод получается по средствам интернет сервиса.

Приложение Translater Android Studio

Напишем 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, но что вы будите делать с данными и базы данных или из внешних файлов? Сделаете в базе данных кучу полей под все языки, это конечно круто, но очень трудоемко. А вот воспользоваться переводчиком очень неплохое решение, и если перевод не удался показать английский вариант. Можно даже при первом запуске приложения сделать полный перевод на язык лакали всех данных из базы данных и потом интернет для перевода будет не нужен.

Поделись с друзьями:
Если вам понравилась статья, подписывайтесь на наши социальные сети.

Оставьте комментарий

пять × 4 =