Skip to content

Commit

Permalink
Regression: AutoTranslate on new message template (#26049)
Browse files Browse the repository at this point in the history
Co-authored-by: Tasso Evangelista <tasso.evangelista@rocket.chat>
  • Loading branch information
2 people authored and ggazzo committed Jul 18, 2022
1 parent d3c5281 commit 3ba18af
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 61 deletions.
4 changes: 2 additions & 2 deletions apps/meteor/app/autotranslate/client/lib/actionButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Meteor.startup(() => {
Messages.update({ _id: message._id }, { [action]: { autoTranslateShowInverse: true } });
},
condition({ message, user }) {
return Boolean(message?.u && message.u._id !== user._id && isTranslatedMessage(message) && !message.translations.original);
return Boolean(message?.u && message.u._id !== user._id && isTranslatedMessage(message) && message.autoTranslateShowInverse);
},
order: 90,
});
Expand All @@ -54,7 +54,7 @@ Meteor.startup(() => {
Messages.update({ _id: message._id }, { [action]: { autoTranslateShowInverse: true } });
},
condition({ message, user }) {
return Boolean(message?.u && message.u._id !== user._id && isTranslatedMessage(message) && message.translations.original);
return Boolean(message?.u && message.u._id !== user._id && isTranslatedMessage(message) && !message.autoTranslateShowInverse);
},
order: 90,
});
Expand Down
51 changes: 41 additions & 10 deletions apps/meteor/app/autotranslate/client/lib/autotranslate.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import _ from 'underscore';
import mem from 'mem';
import { IRoom, ISubscription, ISupportedLanguage, ITranslatedMessage, IUser, MessageAttachmentDefault } from '@rocket.chat/core-typings';

Expand All @@ -24,7 +23,7 @@ Meteor.startup(() => {

export const AutoTranslate = {
initialized: false,
providersMetadata: {},
providersMetadata: {} as { [providerNamer: string]: { name: string; displayName: string } },
messageIdsToWait: {} as { [messageId: string]: string },
supportedLanguages: [] as ISupportedLanguage[],

Expand All @@ -37,22 +36,38 @@ export const AutoTranslate = {
}
const language = (subscription?.autoTranslateLanguage || userLanguage || window.defaultUserLanguage?.()) as string;
if (language.indexOf('-') !== -1) {
if (!_.findWhere(this.supportedLanguages, { language })) {
return language.substr(0, 2);
if (!this.supportedLanguages.some((supportedLanguage) => supportedLanguage.language === language)) {
return language.slice(0, 2);
}
}
return language;
},

translateAttachments(attachments: MessageAttachmentDefault[], language: string): MessageAttachmentDefault[] {
translateAttachments(
attachments: MessageAttachmentDefault[],
language: string,
autoTranslateShowInverse: boolean,
): MessageAttachmentDefault[] {
for (const attachment of attachments) {
if (attachment.author_name !== username) {
if (attachment.text && attachment.translations && attachment.translations[language]) {
attachment.text = attachment.translations[language];
attachment.translations.original = attachment.text;

if (autoTranslateShowInverse) {
attachment.text = attachment.translations.original;
} else {
attachment.text = attachment.translations[language];
}
}

if (attachment.description && attachment.translations && attachment.translations[language]) {
attachment.description = attachment.translations[language];
attachment.translations.original = attachment.description;

if (autoTranslateShowInverse) {
attachment.description = attachment.translations.original;
} else {
attachment.description = attachment.translations[language];
}
}

// @ts-expect-error - not sure what to do with this
Expand Down Expand Up @@ -107,17 +122,33 @@ export const createAutoTranslateMessageRenderer = (): ((message: ITranslatedMess
message.translations = {};
}
if (!!subscription?.autoTranslate !== !!message.autoTranslateShowInverse) {
const hasAttachmentsTranslate =
message.attachments?.some(
(attachment) =>
'translations' in attachment &&
typeof attachment.translations === 'object' &&
autoTranslateLanguage in attachment.translations,
) ?? false;

message.translations.original = message.html;
if (message.translations[autoTranslateLanguage]) {
if (message.translations[autoTranslateLanguage] && !hasAttachmentsTranslate) {
message.html = message.translations[autoTranslateLanguage];
}

if (message.attachments && message.attachments.length > 0) {
message.attachments = AutoTranslate.translateAttachments(message.attachments, autoTranslateLanguage);
message.attachments = AutoTranslate.translateAttachments(
message.attachments,
autoTranslateLanguage,
!!message.autoTranslateShowInverse,
);
}
}
} else if (message.attachments && message.attachments.length > 0) {
message.attachments = AutoTranslate.translateAttachments(message.attachments, autoTranslateLanguage);
message.attachments = AutoTranslate.translateAttachments(
message.attachments,
autoTranslateLanguage,
!!message.autoTranslateShowInverse,
);
}
return message;
};
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/app/autotranslate/server/autotranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ export abstract class AutoTranslate {
const translations = this._translateAttachmentDescriptions(attachment, targetLanguages);
if (!_.isEmpty(translations)) {
Messages.addAttachmentTranslations(message._id, index, translations);
Messages.addTranslations(message._id, translations, TranslationProviderRegistry[Provider]);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { UserPresence } from '../../../../lib/presence';
import MessageBlockUiKit from '../../../blocks/MessageBlock';
import MessageLocation from '../../../location/MessageLocation';
import { useMessageActions, useMessageOembedIsEnabled, useMessageRunActionLink } from '../../contexts/MessageContext';
import { useMessageListShowReadReceipt } from '../contexts/MessageListContext';
import { useTranslateAttachments, useMessageListShowReadReceipt } from '../contexts/MessageListContext';
import { isOwnUserMessage } from '../lib/isOwnUserMessage';
import MessageContentBody from './MessageContentBody';
import ReactionsList from './MessageReactionsList';
Expand Down Expand Up @@ -44,6 +44,8 @@ const MessageContent: FC<{ message: IMessage; sequential: boolean; subscription?

const isEncryptedMessage = isE2EEMessage(message);

const messageAttachments = useTranslateAttachments({ message });

return (
<>
{!message.blocks && (message.md || message.msg) && (
Expand All @@ -58,7 +60,7 @@ const MessageContent: FC<{ message: IMessage; sequential: boolean; subscription?
<MessageBlockUiKit mid={message._id} blocks={message.blocks} appId rid={message.rid} />
</MessageBlock>
)}
{message.attachments && <Attachments attachments={message.attachments} file={message.file} />}
{messageAttachments && <Attachments attachments={messageAttachments} file={message.file} />}

{oembedIsEnabled && !!message.urls?.length && <PreviewList urls={message.urls} />}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,56 +1,48 @@
import { IMessage, isEditedMessage, isE2EEMessage, isOTRMessage } from '@rocket.chat/core-typings';
import { MessageStatusIndicator, MessageStatusIndicatorItem } from '@rocket.chat/fuselage';
import { IMessage, isEditedMessage, ITranslatedMessage, isE2EEMessage, isOTRMessage } from '@rocket.chat/core-typings';
import { MessageStatusIndicator, MessageStatusIndicatorItem, MessageStatusIndicatorText } from '@rocket.chat/fuselage';
import { useUserId, useTranslation } from '@rocket.chat/ui-contexts';
import React, { FC } from 'react';

import { useMessageDateFormatter, useShowStarred, useShowTranslated, useShowFollowing } from '../contexts/MessageListContext';

// edited() {
// const { msg } = this;
// return msg.editedAt && !MessageTypes.isSystemMessage(msg);
// },
// editTime() {
// const { msg } = this;
// return msg.editedAt ? formatDateAndTime(msg.editedAt) : '';
// },
// editedBy() {
// const { msg } = this;
// if (!msg.editedAt) {
// return '';
// }
// // try to return the username of the editor,
// // otherwise a special "?" character that will be
// // rendered as a special avatar
// return (msg.editedBy && msg.editedBy.username) || '?';
// },
import {
useMessageDateFormatter,
useShowStarred,
useShowTranslated,
useShowFollowing,
useTranslateProvider,
} from '../contexts/MessageListContext';

export const MessageIndicators: FC<{
message: IMessage;
message: IMessage & Partial<ITranslatedMessage>;
}> = ({ message }) => {
const t = useTranslation();
const translated = useShowTranslated({ message }); // TODO: useMessageTranslated
const starred = useShowStarred({ message }); // TODO: useMessageStarred
const following = useShowFollowing({ message }); // TODO: useMessageFollowing
const translated = useShowTranslated({ message });
const translateProvider = useTranslateProvider({ message });
const starred = useShowStarred({ message });
const following = useShowFollowing({ message });

const isEncryptedMessage = isE2EEMessage(message);
const isOtrMessage = isOTRMessage(message);

const uid = useUserId();

const formatter = useMessageDateFormatter(); // TODO: useMessageDateFormatter
const formatter = useMessageDateFormatter();

return (
<MessageStatusIndicator>
{translated && <MessageStatusIndicatorItem name='pin' data-title={t('Message_has_been_pinned')} />}
{translated && (
<MessageStatusIndicatorText>
<MessageStatusIndicatorItem name='language' title={t('Translated')} /> {translateProvider}
</MessageStatusIndicatorText>
)}

{following && <MessageStatusIndicatorItem name='bell' data-title={t('Following')} />}
{following && <MessageStatusIndicatorItem name='bell' title={t('Following')} />}

{message.sentByEmail && <MessageStatusIndicatorItem name='mail' data-title={t('Message_sent_by_email')} />}
{message.sentByEmail && <MessageStatusIndicatorItem name='mail' title={t('Message_sent_by_email')} />}
{isEditedMessage(message) && (
<MessageStatusIndicatorItem
name='edit'
color={message.u._id !== message.editedBy._id ? 'danger' : undefined}
data-title={
title={
message.editedBy._id === uid
? t('Message_has_been_edited_at', { date: formatter(message.editedAt) })
: t('Message_has_been_edited_by_at', {
Expand All @@ -60,13 +52,13 @@ export const MessageIndicators: FC<{
}
/>
)}
{message.pinned && <MessageStatusIndicatorItem name='pin' data-title={t('Message_has_been_pinned')} />}
{message.pinned && <MessageStatusIndicatorItem name='pin' title={t('Message_has_been_pinned')} />}

{isEncryptedMessage && <MessageStatusIndicatorItem name='key' />}

{isOtrMessage && <MessageStatusIndicatorItem name='stopwatch' />}

{starred && <MessageStatusIndicatorItem name='star-filled' data-title={t('Message_has_been_starred')} />}
{starred && <MessageStatusIndicatorItem name='star-filled' title={t('Message_has_been_starred')} />}
</MessageStatusIndicator>
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { IMessage } from '@rocket.chat/core-typings';
import { IMessage, MessageAttachment } from '@rocket.chat/core-typings';
import { createContext, useContext } from 'react';

export type MessageListContextValue = {
useShowTranslated: ({ message }: { message: IMessage }) => boolean;
useTranslateProvider: ({ message }: { message: IMessage }) => string | boolean;
useTranslateAttachments: ({ message }: { message: IMessage }) => MessageAttachment[];
useShowStarred: ({ message }: { message: IMessage }) => boolean;
useShowFollowing: ({ message }: { message: IMessage }) => boolean;
useMessageDateFormatter: () => (date: Date) => string;
Expand All @@ -28,6 +30,8 @@ export type MessageListContextValue = {

export const MessageListContext = createContext<MessageListContextValue>({
useShowTranslated: () => false,
useTranslateProvider: () => false,
useTranslateAttachments: () => [],
useShowStarred: () => false,
useShowFollowing: () => false,
useUserHasReacted: () => (): boolean => false,
Expand All @@ -49,6 +53,10 @@ export const MessageListContext = createContext<MessageListContextValue>({

export const useShowTranslated: MessageListContextValue['useShowTranslated'] = (...args) =>
useContext(MessageListContext).useShowTranslated(...args);
export const useTranslateProvider: MessageListContextValue['useTranslateProvider'] = (...args) =>
useContext(MessageListContext).useTranslateProvider(...args);
export const useTranslateAttachments: MessageListContextValue['useTranslateAttachments'] = (...args) =>
useContext(MessageListContext).useTranslateAttachments(...args);
export const useShowStarred: MessageListContextValue['useShowStarred'] = (...args) =>
useContext(MessageListContext).useShowStarred(...args);
export const useShowFollowing: MessageListContextValue['useShowFollowing'] = (...args) =>
Expand Down
32 changes: 21 additions & 11 deletions apps/meteor/client/views/room/MessageList/hooks/useParsedMessage.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
import { IMessage } from '@rocket.chat/core-typings';
import { IMessage, isTranslatedMessage, ITranslatedMessage } from '@rocket.chat/core-typings';
import { Root, parse } from '@rocket.chat/message-parser';
import { useSetting } from '@rocket.chat/ui-contexts';
import { useMemo } from 'react';

export function useParsedMessage(message: Pick<IMessage, 'md' | 'msg'>): Root {
import { useShowTranslated } from '../contexts/MessageListContext';
import { useAutotranslateLanguage } from './useAutotranslateLanguage';

export function useParsedMessage(message: IMessage & Partial<ITranslatedMessage>): Root {
const colors = useSetting('HexColorPreview_Enabled') as boolean;
const katexDollarSyntax = useSetting('Katex_Dollar_Syntax') as boolean;
const katexParenthesisSyntax = useSetting('Katex_Parenthesis_Syntax') as boolean;
const autoTranslateLanguage = useAutotranslateLanguage(message.rid);
const translated = useShowTranslated({ message });

return useMemo(() => {
const parseOptions = {
colors,
emoticons: true,
katex: {
dollarSyntax: katexDollarSyntax,
parenthesisSyntax: katexParenthesisSyntax,
},
};

if (translated && autoTranslateLanguage && isTranslatedMessage(message)) {
return parse(message.translations[autoTranslateLanguage], parseOptions);
}
if (message.md) {
return message.md;
}
Expand All @@ -17,13 +34,6 @@ export function useParsedMessage(message: Pick<IMessage, 'md' | 'msg'>): Root {
return [];
}

return parse(message.msg, {
colors,
emoticons: true,
katex: {
dollarSyntax: katexDollarSyntax,
parenthesisSyntax: katexParenthesisSyntax,
},
});
}, [colors, katexDollarSyntax, katexParenthesisSyntax, message.md, message.msg]);
return parse(message.msg, parseOptions);
}, [colors, katexDollarSyntax, katexParenthesisSyntax, autoTranslateLanguage, message.md, message.msg, message.translations]);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { IRoom, IMessage, isTranslatedMessage, isMessageReactionsNormalized, isThreadMainMessage } from '@rocket.chat/core-typings';
import {
IRoom,
IMessage,
isTranslatedMessage,
isMessageReactionsNormalized,
MessageAttachment,
isThreadMainMessage,
} from '@rocket.chat/core-typings';
import { useLayout, useUser, useUserPreference, useUserSubscription, useSetting, useEndpoint, useUserRoom } from '@rocket.chat/ui-contexts';
import React, { useMemo, FC, memo } from 'react';

import { AutoTranslate } from '../../../../../app/autotranslate/client';
import { EmojiPicker } from '../../../../../app/emoji/client';
import { getRegexHighlight, getRegexHighlightUrl } from '../../../../../app/highlight-words/client/helper';
import ToolboxProvider from '../../providers/ToolboxProvider';
Expand Down Expand Up @@ -72,8 +80,27 @@ export const MessageListProvider: FC<{
useShowTranslated:
uid && autoTranslateEnabled && hasSubscription && autoTranslateLanguage
? ({ message }): boolean =>
message.u && message.u._id !== uid && isTranslatedMessage(message) && Boolean(message.translations[autoTranslateLanguage])
Boolean(message.u) &&
message.u?._id !== uid &&
isTranslatedMessage(message) &&
Boolean(message.translations[autoTranslateLanguage]) &&
!message.autoTranslateShowInverse
: (): boolean => false,
useTranslateProvider:
autoTranslateEnabled && autoTranslateLanguage
? ({ message }): string | boolean =>
isTranslatedMessage(message) && AutoTranslate.providersMetadata[message.translationProvider]?.displayName
: (): boolean => false,
useTranslateAttachments:
uid && autoTranslateEnabled && hasSubscription && autoTranslateLanguage
? ({ message }): MessageAttachment[] =>
(isTranslatedMessage(message) &&
message.u?._id !== uid &&
message.attachments &&
AutoTranslate.translateAttachments(message.attachments, autoTranslateLanguage, !!message.autoTranslateShowInverse)) ||
message.attachments ||
[]
: ({ message }): MessageAttachment[] => message.attachments || [],
useShowStarred: hasSubscription
? ({ message }): boolean => Boolean(Array.isArray(message.starred) && message.starred.find((star) => star._id === uid))
: (): boolean => false,
Expand Down
1 change: 1 addition & 0 deletions packages/core-typings/src/IMessage/IMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ export const isEditedMessage = (message: IMessage): message is IEditedMessage =>

export interface ITranslatedMessage extends IMessage {
translations: { [key: string]: string } & { original?: string };
translationProvider: string;
autoTranslateShowInverse?: boolean;
autoTranslateFetching?: boolean;
}
Expand Down

0 comments on commit 3ba18af

Please sign in to comment.