diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c9ce563ec..05ab0ba8e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -189,6 +189,10 @@
android:name=".location.GeocodingActivity"
android:theme="@style/AppTheme" />
+
+
diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApi.java b/app/src/main/java/com/nextcloud/talk/api/NcApi.java
index 6204f5218..6bf7f984c 100644
--- a/app/src/main/java/com/nextcloud/talk/api/NcApi.java
+++ b/app/src/main/java/com/nextcloud/talk/api/NcApi.java
@@ -44,6 +44,7 @@ import com.nextcloud.talk.models.json.search.ContactsByNumberOverall;
import com.nextcloud.talk.models.json.signaling.SignalingOverall;
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
import com.nextcloud.talk.models.json.status.StatusOverall;
+import com.nextcloud.talk.models.json.translations.TranslationsOverall;
import com.nextcloud.talk.models.json.unifiedsearch.UnifiedSearchOverall;
import com.nextcloud.talk.models.json.userprofile.UserProfileFieldsOverall;
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
@@ -654,4 +655,12 @@ public interface NcApi {
@DELETE
Observable sendCommonDeleteRequest(@Header("Authorization") String authorization, @Url String url);
+
+
+ @POST
+ Observable translateMessage(@Header("Authorization") String authorization,
+ @Url String url,
+ @Query("text") String text,
+ @Query("toLanguage") String toLanguage,
+ @Nullable @Query("fromLanguage") String fromLanguage);
}
diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
index 292911191..0a23661bf 100644
--- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
+++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
@@ -150,6 +150,7 @@ import com.nextcloud.talk.remotefilebrowser.activities.RemoteFileBrowserActivity
import com.nextcloud.talk.repositories.reactions.ReactionsRepository
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
import com.nextcloud.talk.signaling.SignalingMessageReceiver
+import com.nextcloud.talk.translate.TranslateActivity
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
import com.nextcloud.talk.ui.dialog.AttachmentDialog
import com.nextcloud.talk.ui.dialog.MessageActionsDialog
@@ -3231,6 +3232,15 @@ class ChatActivity :
clipboardManager.setPrimaryClip(clipData)
}
+ fun translateMessage(message: IMessage?) {
+ val bundle = Bundle()
+ bundle.putString(BundleKeys.KEY_TRANSLATE_MESSAGE, message?.text)
+
+ val intent = Intent(this, TranslateActivity::class.java)
+ intent.putExtras(bundle)
+ startActivity(intent)
+ }
+
private fun hasVisibleItems(message: ChatMessage): Boolean {
return !message.isDeleted || // copy message
message.replyable || // reply to
diff --git a/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslateData.kt b/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslateData.kt
new file mode 100644
index 000000000..9ebfdd971
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslateData.kt
@@ -0,0 +1,37 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Julius Linus
+ * Copyright (C) 2023 Julius Linus
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.nextcloud.talk.models.json.translations
+
+import android.os.Parcelable
+import com.bluelinelabs.logansquare.annotation.JsonField
+import com.bluelinelabs.logansquare.annotation.JsonObject
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+@JsonObject
+data class TranslateData(
+ @JsonField(name = ["text"])
+ var text: String?,
+ @JsonField(name = ["from"])
+ var fromLanguage: String?
+) : Parcelable {
+ // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+ constructor() : this(null, null)
+}
diff --git a/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslateOCS.kt b/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslateOCS.kt
new file mode 100644
index 000000000..74ba31327
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslateOCS.kt
@@ -0,0 +1,38 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Julius Linus
+ * Copyright (C) 2023 Julius Linus
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.nextcloud.talk.models.json.translations
+
+import android.os.Parcelable
+import com.bluelinelabs.logansquare.annotation.JsonField
+import com.bluelinelabs.logansquare.annotation.JsonObject
+import com.nextcloud.talk.models.json.generic.GenericMeta
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+@JsonObject
+data class TranslateOCS( // TODO finish this model
+ @JsonField(name = ["meta"])
+ var meta: GenericMeta?,
+ @JsonField(name = ["data"])
+ var data: TranslateData?
+) : Parcelable {
+ // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+ constructor() : this(null, TranslateData())
+}
diff --git a/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslationsOverall.kt b/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslationsOverall.kt
new file mode 100644
index 000000000..1b832e9cd
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/models/json/translations/TranslationsOverall.kt
@@ -0,0 +1,35 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Julius Linus
+ * Copyright (C) 2023 Julius Linus
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.nextcloud.talk.models.json.translations
+
+import android.os.Parcelable
+import com.bluelinelabs.logansquare.annotation.JsonField
+import com.bluelinelabs.logansquare.annotation.JsonObject
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+@JsonObject
+class TranslationsOverall(
+ @JsonField(name = ["ocs"])
+ var ocs: TranslateOCS?
+) : Parcelable {
+ // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
+ constructor() : this(null)
+}
diff --git a/app/src/main/java/com/nextcloud/talk/translate/TranslateActivity.kt b/app/src/main/java/com/nextcloud/talk/translate/TranslateActivity.kt
new file mode 100644
index 000000000..b9bb17e8e
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/translate/TranslateActivity.kt
@@ -0,0 +1,279 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Julius Linus
+ * @author Andy Scherzinger
+ * Copyright (C) 2023 Julius Linus
+ * Copyright (C) 2023 Andy Scherzinger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.nextcloud.talk.translate
+
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import android.text.method.ScrollingMovementMethod
+import android.util.Log
+import android.view.View
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.appcompat.app.AlertDialog
+import autodagger.AutoInjector
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.nextcloud.talk.R
+import com.nextcloud.talk.activities.BaseActivity
+import com.nextcloud.talk.api.NcApi
+import com.nextcloud.talk.application.NextcloudTalkApplication
+import com.nextcloud.talk.data.user.model.User
+import com.nextcloud.talk.databinding.ActivityTranslateBinding
+import com.nextcloud.talk.models.json.translations.TranslationsOverall
+import com.nextcloud.talk.users.UserManager
+import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.bundle.BundleKeys
+import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
+import io.reactivex.Observer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+import org.json.JSONArray
+import java.util.Locale
+import javax.inject.Inject
+
+@AutoInjector(NextcloudTalkApplication::class)
+class TranslateActivity : BaseActivity() {
+ private lateinit var binding: ActivityTranslateBinding
+
+ @Inject
+ lateinit var ncApi: NcApi
+
+ @Inject
+ lateinit var userManager: UserManager
+
+ var fromLanguages = arrayOf()
+
+ var toLanguages = arrayOf()
+
+ var text: String? = null
+
+ var check: Int = 0
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
+ binding = ActivityTranslateBinding.inflate(layoutInflater)
+
+ setupActionBar()
+ setContentView(binding.root)
+ setupSystemColors()
+ setupTextViews()
+ setupSpinners()
+ getLanguageOptions()
+ translate(null, Locale.getDefault().language)
+ }
+
+ private fun setupActionBar() {
+ setSupportActionBar(binding.translationToolbar)
+ binding.translationToolbar.setNavigationOnClickListener {
+ onBackPressed()
+ }
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ supportActionBar?.setDisplayShowHomeEnabled(true)
+ supportActionBar?.setIcon(ColorDrawable(resources!!.getColor(R.color.transparent)))
+ supportActionBar?.title = resources!!.getString(R.string.translation)
+ viewThemeUtils.material.themeToolbar(binding.translationToolbar)
+ }
+
+ private fun setupTextViews() {
+ val original = binding.originalMessageTextview
+ val translation = binding.translatedMessageTextview
+
+ viewThemeUtils.talk.themeIncomingMessageBubble(original, grouped = true, deleted = false)
+ viewThemeUtils.talk.themeIncomingMessageBubble(translation, grouped = true, deleted = false)
+
+ original.movementMethod = ScrollingMovementMethod()
+ translation.movementMethod = ScrollingMovementMethod()
+
+ val bundle = intent.extras
+ binding.originalMessageTextview.text = bundle?.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
+ text = bundle?.getString(BundleKeys.KEY_TRANSLATE_MESSAGE)
+ }
+
+ private fun getLanguageOptions() {
+ val currentUser: User = userManager.currentUser.blockingGet()
+ val json = JSONArray(CapabilitiesUtilNew.getLanguages(currentUser).toString())
+
+ val fromLanguagesSet = mutableSetOf(resources.getString(R.string.translation_detect_language))
+ val toLanguagesSet = mutableSetOf(resources.getString(R.string.translation_device_settings))
+
+ for (i in 0 until json.length()) {
+ val current = json.getJSONObject(i)
+ if (current.getString(FROM_ID) != Locale.getDefault().language) {
+ toLanguagesSet.add(current.getString(FROM_LABEL))
+ }
+
+ fromLanguagesSet.add(current.getString(TO_LABEL))
+ }
+
+ fromLanguages = fromLanguagesSet.toTypedArray()
+ toLanguages = toLanguagesSet.toTypedArray()
+
+ fillSpinners()
+ }
+
+ private fun enableSpinners(value: Boolean) {
+ binding.fromLanguageInputLayout.isEnabled = value
+ binding.toLanguageInputLayout.isEnabled = value
+ }
+
+ private fun translate(fromLanguage: String?, toLanguage: String) {
+ val currentUser: User = userManager.currentUser.blockingGet()
+ val credentials: String = ApiUtils.getCredentials(currentUser.username, currentUser.token)
+ val translateURL = ApiUtils.getUrlForTranslation(currentUser.baseUrl)
+ val calculatedFromLanguage = if (fromLanguage == null || fromLanguage == "") {
+ null
+ } else {
+ fromLanguage
+ }
+
+ Log.i(TAG, "Url is: $translateURL")
+ ncApi.translateMessage(credentials, translateURL, text, toLanguage, calculatedFromLanguage)
+ ?.subscribeOn(Schedulers.io())
+ ?.observeOn(AndroidSchedulers.mainThread())
+ ?.subscribe(object : Observer {
+ override fun onSubscribe(d: Disposable) {
+ enableSpinners(false)
+ binding.translatedMessageTextview.visibility = View.GONE
+ binding.progressBar.visibility = View.VISIBLE
+ }
+
+ override fun onNext(translationOverall: TranslationsOverall) {
+ binding.progressBar.visibility = View.GONE
+ binding.translatedMessageTextview.visibility = View.VISIBLE
+ binding.translatedMessageTextview.text = translationOverall.ocs?.data?.text
+ }
+
+ override fun onError(e: Throwable) {
+ Log.w(TAG, "Error while translating message", e)
+ binding.progressBar.visibility = View.GONE
+ val dialogBuilder = MaterialAlertDialogBuilder(this@TranslateActivity)
+ .setIcon(
+ viewThemeUtils.dialog.colorMaterialAlertDialogIcon(
+ context,
+ R.drawable.ic_warning_white
+ )
+ )
+ .setTitle(R.string.translation_error_title)
+ .setMessage(R.string.translation_error_message)
+ .setPositiveButton(R.string.nc_ok) { dialog, _ ->
+ dialog.dismiss()
+ }
+
+ viewThemeUtils.dialog.colorMaterialAlertDialogBackground(context, dialogBuilder)
+
+ val dialog = dialogBuilder.show()
+
+ viewThemeUtils.platform.colorTextButtons(
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE)
+ )
+ }
+
+ override fun onComplete() {
+ // nothing?
+ }
+ })
+
+ enableSpinners(true)
+ }
+
+ private fun getISOFromLanguage(language: String): String {
+ if (resources.getString(R.string.translation_device_settings).equals(language)) {
+ return Locale.getDefault().language
+ }
+
+ return getISOFromServer(language)
+ }
+
+ private fun getISOFromServer(language: String): String {
+ val currentUser: User = userManager.currentUser.blockingGet()
+ val json = JSONArray(CapabilitiesUtilNew.getLanguages(currentUser).toString())
+
+ for (i in 0..json.length() - 1) {
+ val current = json.getJSONObject(i)
+ if (current.getString(FROM_LABEL) == language) {
+ return current.getString(FROM_ID)
+ }
+ }
+
+ return ""
+ }
+
+ private fun setupSpinners() {
+ viewThemeUtils.material.colorTextInputLayout(binding.fromLanguageInputLayout)
+ viewThemeUtils.material.colorTextInputLayout(binding.toLanguageInputLayout)
+ fillSpinners()
+
+ binding.fromLanguage.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
+ if (++check > 1) {
+ val fromLabel: String = getISOFromLanguage(parent.getItemAtPosition(position).toString())
+ val toLabel: String = getISOFromLanguage(binding.fromLanguage.text.toString())
+ Log.i(TAG, "fromLanguageSpinner :: $FROM_LABEL = $fromLabel, $TO_LABEL = $ count: $check")
+ translate(fromLabel, toLabel)
+ }
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>) {
+ // write code to perform some action
+ }
+ }
+
+ binding.toLanguage.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
+ if (++check > 2) {
+ val toLabel: String = getISOFromLanguage(parent.getItemAtPosition(position).toString())
+ val fromLabel: String = getISOFromLanguage(binding.fromLanguage.text.toString())
+ Log.i(TAG, "toLanguageSpinner :: $FROM_LABEL = $fromLabel, $TO_LABEL = $toLabel count: $check")
+ translate(fromLabel, toLabel)
+ }
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>) {
+ // write code to perform some action
+ }
+ }
+ }
+
+ private fun fillSpinners() {
+ binding.fromLanguage.setAdapter(
+ ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, fromLanguages)
+ )
+ if (fromLanguages.isNotEmpty()) {
+ binding.fromLanguage.setText(fromLanguages[0])
+ }
+
+ binding.toLanguage.setAdapter(
+ ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, toLanguages)
+ )
+ if (toLanguages.isNotEmpty()) {
+ binding.toLanguage.setText(toLanguages[0])
+ }
+ }
+
+ companion object {
+ private val TAG = TranslateActivity::class.simpleName
+ private const val FROM_ID = "from"
+ private const val FROM_LABEL = "fromLabel"
+ private const val TO_LABEL = "toLabel"
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt
index 9b93117fc..87384a286 100644
--- a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt
+++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt
@@ -55,6 +55,7 @@ import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
+import org.json.JSONArray
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@@ -88,6 +89,12 @@ class MessageActionsDialog(
viewThemeUtils.platform.themeDialog(dialogMessageActionsBinding.root)
initEmojiBar(hasChatPermission)
initMenuItemCopy(!message.isDeleted)
+ initMenuItemTranslate(
+ !message.isDeleted &&
+ ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getCalculateMessageType() &&
+ CapabilitiesUtilNew.isTranslationsSupported(user) &&
+ JSONArray(CapabilitiesUtilNew.getLanguages(user).toString()).length() > 0
+ )
initMenuReplyToMessage(message.replyable && hasChatPermission)
initMenuReplyPrivately(
message.replyable &&
@@ -296,6 +303,17 @@ class MessageActionsDialog(
dialogMessageActionsBinding.menuCopyMessage.visibility = getVisibility(visible)
}
+ private fun initMenuItemTranslate(visible: Boolean) {
+ if (visible) {
+ dialogMessageActionsBinding.menuTranslateMessage.setOnClickListener {
+ chatActivity.translateMessage(message)
+ dismiss()
+ }
+ }
+
+ dialogMessageActionsBinding.menuTranslateMessage.visibility = getVisibility(visible)
+ }
+
private fun getVisibility(visible: Boolean): Int {
return if (visible) {
View.VISIBLE
diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt
index b4b78bd81..93e833f7c 100644
--- a/app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt
+++ b/app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt
@@ -28,7 +28,6 @@ import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Build
import android.view.View
-import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.ColorInt
@@ -65,7 +64,7 @@ class TalkSpecificViewThemeUtils @Inject constructor(
private val appcompat: AndroidXViewThemeUtils
) :
ViewThemeUtilsBase(schemes) {
- fun themeIncomingMessageBubble(bubble: ViewGroup, grouped: Boolean, deleted: Boolean) {
+ fun themeIncomingMessageBubble(bubble: View, grouped: Boolean, deleted: Boolean) {
val resources = bubble.resources
var bubbleResource = R.drawable.shape_incoming_message
@@ -88,7 +87,7 @@ class TalkSpecificViewThemeUtils @Inject constructor(
ViewCompat.setBackground(bubble, bubbleDrawable)
}
- fun themeOutgoingMessageBubble(bubble: ViewGroup, grouped: Boolean, deleted: Boolean) {
+ fun themeOutgoingMessageBubble(bubble: View, grouped: Boolean, deleted: Boolean) {
withScheme(bubble) { scheme ->
val bgBubbleColor = if (deleted) {
ColorUtils.setAlphaComponent(scheme.surfaceVariant, HALF_ALPHA_INT)
diff --git a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
index bc4b04027..7c209e574 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
+++ b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
@@ -526,4 +526,8 @@ public class ApiUtils {
public static String getUrlForConversationDescription(int version, String baseUrl, String token) {
return getUrlForRoom(version, baseUrl, token) + "/description";
}
+
+ public static String getUrlForTranslation(String baseUrl) {
+ return baseUrl + ocsApiVersion + "/translation/translate";
+ }
}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt b/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
index dc6a893d3..88f8acb4a 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
+++ b/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
@@ -29,6 +29,7 @@ object BundleKeys {
const val KEY_SELECTED_EMAILS = "KEY_SELECTED_EMAILS"
const val KEY_USERNAME = "KEY_USERNAME"
const val KEY_TOKEN = "KEY_TOKEN"
+ const val KEY_TRANSLATE_MESSAGE = "KEY_TRANSLATE_MESSAGE"
const val KEY_BASE_URL = "KEY_BASE_URL"
const val KEY_IS_ACCOUNT_IMPORT = "KEY_IS_ACCOUNT_IMPORT"
const val KEY_ORIGINAL_PROTOCOL = "KEY_ORIGINAL_PROTOCOL"
diff --git a/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt b/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt
index 2c1802faf..d91a4178f 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt
+++ b/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesUtilNew.kt
@@ -199,5 +199,24 @@ object CapabilitiesUtilNew {
return false
}
+ fun isTranslationsSupported(user: User?): Boolean {
+ if (user?.capabilities != null) {
+ val capabilities = user.capabilities
+ return capabilities?.spreedCapability?.config?.containsKey("chat") == true &&
+ capabilities.spreedCapability!!.config!!["chat"] != null &&
+ capabilities.spreedCapability!!.config!!["chat"]!!.containsKey("translations")
+ }
+
+ return false
+ }
+
+ fun getLanguages(user: User?): Any? {
+ return if (isTranslationsSupported(user)) {
+ user!!.capabilities!!.spreedCapability!!.config!!["chat"]!!["translations"]
+ } else {
+ null
+ }
+ }
+
const val DEFAULT_CHAT_SIZE = 1000
}
diff --git a/app/src/main/res/drawable-night/ic_chevron_right.xml b/app/src/main/res/drawable-night/ic_chevron_right.xml
new file mode 100644
index 000000000..253ff96a2
--- /dev/null
+++ b/app/src/main/res/drawable-night/ic_chevron_right.xml
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_translate_24.xml b/app/src/main/res/drawable/ic_baseline_translate_24.xml
new file mode 100644
index 000000000..4b511684c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_translate_24.xml
@@ -0,0 +1,26 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_chevron_right.xml b/app/src/main/res/drawable/ic_chevron_right.xml
new file mode 100644
index 000000000..91ec3a701
--- /dev/null
+++ b/app/src/main/res/drawable/ic_chevron_right.xml
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/app/src/main/res/layout-land/activity_translate.xml b/app/src/main/res/layout-land/activity_translate.xml
new file mode 100644
index 000000000..144fd2010
--- /dev/null
+++ b/app/src/main/res/layout-land/activity_translate.xml
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_translate.xml b/app/src/main/res/layout/activity_translate.xml
new file mode 100644
index 000000000..8dbdd7977
--- /dev/null
+++ b/app/src/main/res/layout/activity_translate.xml
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_message_actions.xml b/app/src/main/res/layout/dialog_message_actions.xml
index ebd2987f0..ebbf99827 100644
--- a/app/src/main/res/layout/dialog_message_actions.xml
+++ b/app/src/main/res/layout/dialog_message_actions.xml
@@ -287,6 +287,39 @@
+
+
+
+
+
+
+
+
You are not allowed to activate audio!
You are not allowed to activate video!
Scroll to bottom
+ Translate
+ Translation
+ From
+ To
+ Detect language
+ Device settings
+ Translation failed
+ Could not detect language