@@ -214,6 +221,7 @@ import CheckAll from 'vue-material-design-icons/CheckAll.vue'
import EmoticonOutline from 'vue-material-design-icons/EmoticonOutline.vue'
import Reload from 'vue-material-design-icons/Reload.vue'
+import { getCapabilities } from '@nextcloud/capabilities'
import { showError, showSuccess, showWarning, TOAST_DEFAULT_TIMEOUT } from '@nextcloud/dialogs'
import moment from '@nextcloud/moment'
@@ -225,6 +233,7 @@ import NcRichText from '@nextcloud/vue/dist/Components/NcRichText.js'
import Quote from '../../../Quote.vue'
import CallButton from '../../../TopBar/CallButton.vue'
import MessageButtonsBar from './MessageButtonsBar/MessageButtonsBar.vue'
+import MessageTranslateDialog from './MessageButtonsBar/MessageTranslateDialog.vue'
import Contact from './MessagePart/Contact.vue'
import DeckCard from './MessagePart/DeckCard.vue'
import DefaultParameter from './MessagePart/DefaultParameter.vue'
@@ -238,6 +247,8 @@ import { ATTENDEE, CONVERSATION, PARTICIPANT } from '../../../../constants.js'
import participant from '../../../../mixins/participant.js'
import { EventBus } from '../../../../services/EventBus.js'
+const isTranslationAvailable = getCapabilities()?.spreed?.config?.chat?.translations?.length > 0
+
/**
* @property {object} scrollerBoundingClientRect provided by MessageList.vue
*/
@@ -245,6 +256,7 @@ export default {
name: 'Message',
components: {
+ MessageTranslateDialog,
CallButton,
MessageButtonsBar,
NcButton,
@@ -404,7 +416,7 @@ export default {
setup() {
const isInCall = useIsInCall()
- return { isInCall }
+ return { isInCall, isTranslationAvailable }
},
data() {
@@ -422,6 +434,7 @@ export default {
isReactionsMenuOpen: false,
isForwarderOpen: false,
detailedReactionsLoading: false,
+ isTranslateDialogOpen: false,
}
},
@@ -580,7 +593,9 @@ export default {
},
showMessageButtonsBar() {
- return !this.isSystemMessage && !this.isDeletedMessage && !this.isTemporary && (this.isHovered || this.isActionMenuOpen || this.isEmojiPickerOpen || this.isFollowUpEmojiPickerOpen || this.isReactionsMenuOpen || this.isForwarderOpen)
+ return !this.isSystemMessage && !this.isDeletedMessage && !this.isTemporary
+ && (this.isHovered || this.isActionMenuOpen || this.isEmojiPickerOpen || this.isFollowUpEmojiPickerOpen
+ || this.isReactionsMenuOpen || this.isForwarderOpen || this.isTranslateDialogOpen)
},
isTemporaryUpload() {
diff --git a/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue b/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue
index 49e08d0ae81..354987c1148 100644
--- a/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue
+++ b/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue
@@ -106,6 +106,15 @@
@click="action.callback(messageApiData)">
{{ action.label }}
+
+
+
+
+ {{ t('spreed', 'Translate') }}
+
+ -
+ - @author Marco Ambrosini
+ - @author Maksim Sukharev
+ -
+ - @license AGPL-3.0-or-later
+ -
+ - This program is free software: you can redistribute it and/or modify
+ - it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see .
+-->
+
+
+
+
+
{{ t('spreed', 'Translate message') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ isLoading ? t('spreed', 'Translating') : t('spreed', 'Translate') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('spreed', 'Copy translated text') }}
+
+
+
+
+
+
+
+
+
diff --git a/src/services/messagesService.js b/src/services/messagesService.js
index 6dca4c52a19..b6b3e4bf59f 100644
--- a/src/services/messagesService.js
+++ b/src/services/messagesService.js
@@ -175,6 +175,18 @@ const getReactionsDetails = async function(token, messageId) {
return axios.get(generateOcsUrl('apps/spreed/api/v1/reaction/{token}/{messageId}', { token, messageId }))
}
+const getTranslationLanguages = async function() {
+ return axios.get(generateOcsUrl('/translation/languages'))
+}
+
+const translateText = async function(text, fromLanguage, toLanguage) {
+ return axios.post(generateOcsUrl('/translation/translate'), {
+ text,
+ fromLanguage,
+ toLanguage,
+ })
+}
+
export {
fetchMessages,
lookForNewMessages,
@@ -186,4 +198,6 @@ export {
addReactionToMessage,
removeReactionFromMessage,
getReactionsDetails,
+ getTranslationLanguages,
+ translateText,
}