Skip to content

Commit 2edf02a

Browse files
authored
Merge pull request #384 from GetStream/auto-translate
Auto translate
2 parents ae1448b + e3c4b4c commit 2edf02a

File tree

15 files changed

+392
-69
lines changed

15 files changed

+392
-69
lines changed

docusaurus/docs/Angular/types/stream-message.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The [`StreamMessage`](https://github.com/GetStream/stream-chat-angular/blob/mast
1010

1111
The class extends the base Stream [message](https://getstream.io/chat/docs/javascript/message_format/?language=javascript#open-graph-scraper) format with the following properties:
1212

13-
| Name | Type | Description |
14-
| ------ | -------- | --------------------------------------- |
15-
| readBy | string[] | The list of users that read the message |
13+
| Name | Type | Description |
14+
| ----------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15+
| readBy | string[] | The list of users that read the message |
16+
| translation | string | The message translation if message was translated with [auto-translation](https://getstream.io/chat/docs/javascript/translation/?language=javascript&q=auto%20trasnlate#automatic-translation) |

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"@ngx-translate/core": "^13.0.0",
118118
"@ngx-translate/http-loader": "^6.0.0",
119119
"@popperjs/core": "^2.11.5",
120-
"@stream-io/stream-chat-css": "3.0.0-theming2.11",
120+
"@stream-io/stream-chat-css": "3.3.0",
121121
"@stream-io/transliterate": "^1.5.2",
122122
"angular-mentions": "^1.4.0",
123123
"dayjs": "^1.10.7",

projects/stream-chat-angular/src/assets/i18n/en.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,8 @@ export const en = {
101101
'user is typing': '{{ user }} is typing',
102102
'users are typing': '{{ users }} are typing',
103103
'Error loading channels': 'Error loading channels',
104+
'See original (automatically translated)':
105+
'See original (automatically translated)',
106+
'See translation': 'See translation',
104107
},
105108
};

projects/stream-chat-angular/src/lib/channel-preview/channel-preview.component.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,4 +311,21 @@ describe('ChannelPreviewComponent', () => {
311311

312312
expect(queryLatestMessage()?.textContent).toContain('Nothing yet...');
313313
});
314+
315+
it('should display translated message', () => {
316+
const channel = generateMockChannels()[0];
317+
const latestMessage =
318+
channel.state.latestMessages[channel.state.latestMessages.length - 1];
319+
latestMessage.i18n = {
320+
hu_text: 'Hogy vagy?',
321+
language: 'en',
322+
};
323+
latestMessage.user!.id += 'not';
324+
channel.data!.auto_translation_language = 'hu';
325+
channelServiceMock.activeChannel$.next(channel);
326+
component.channel = channel;
327+
fixture.detectChanges();
328+
329+
expect(queryLatestMessage()?.textContent).toContain('Hogy vagy?');
330+
});
314331
});

projects/stream-chat-angular/src/lib/channel-preview/channel-preview.component.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ChannelService } from '../channel.service';
1010
import { getChannelDisplayText } from '../get-channel-display-text';
1111
import { DefaultStreamChatGenerics } from '../types';
1212
import { ChatClientService } from '../chat-client.service';
13+
import { getMessageTranslation } from '../get-message-translation';
1314

1415
/**
1516
* The `ChannelPreview` component displays a channel preview in the channel list, it consists of the image, name and latest message of the channel.
@@ -122,7 +123,12 @@ export class ChannelPreviewComponent implements OnInit, OnDestroy {
122123
if (message?.deleted_at) {
123124
this.latestMessage = 'streamChat.Message deleted';
124125
} else if (message?.text) {
125-
this.latestMessage = message.text;
126+
this.latestMessage =
127+
getMessageTranslation(
128+
message,
129+
this.channel,
130+
this.chatClientService.chatClient.user
131+
) || message.text;
126132
} else if (message?.attachments && message.attachments.length) {
127133
this.latestMessage = 'streamChat.🏙 Attachment...';
128134
}

projects/stream-chat-angular/src/lib/channel.service.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,16 @@ describe('ChannelService', () => {
11151115
expect(mockChatClient.updateMessage).toHaveBeenCalledWith(message);
11161116
});
11171117

1118+
it('should remove translation object before updating message', () => {
1119+
const message = mockMessage();
1120+
void service.updateMessage({
1121+
...message,
1122+
i18n: { en_text: 'Translation', language: 'en' },
1123+
});
1124+
1125+
expect(mockChatClient.updateMessage).toHaveBeenCalledWith(message);
1126+
});
1127+
11181128
it('should delete message', () => {
11191129
const message = mockMessage();
11201130
void service.deleteMessage(message);

projects/stream-chat-angular/src/lib/channel.service.ts

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
UserResponse,
2424
} from 'stream-chat';
2525
import { ChatClientService, ClientEvent } from './chat-client.service';
26+
import { getMessageTranslation } from './get-message-translation';
2627
import { createMessagePreview } from './message-preview';
2728
import { NotificationService } from './notification.service';
2829
import { getReadBy } from './read-by';
@@ -401,6 +402,18 @@ export class ChannelService<
401402
this.activeChannelSubject.next(channel);
402403
channel.state.messages.forEach((m) => {
403404
m.readBy = getReadBy(m, channel);
405+
m.translation = getMessageTranslation(
406+
m,
407+
channel,
408+
this.chatClientService.chatClient.user
409+
);
410+
if (m.quoted_message) {
411+
m.quoted_message.translation = getMessageTranslation(
412+
m.quoted_message,
413+
channel,
414+
this.chatClientService.chatClient.user
415+
);
416+
}
404417
});
405418
if (this.canSendReadEvents && this.shouldMarkActiveChannelAsRead) {
406419
void channel.markRead();
@@ -668,8 +681,10 @@ export class ChannelService<
668681
* @param message Mesage to be updated
669682
*/
670683
async updateMessage(message: StreamMessage<T>) {
684+
const messageToUpdate = { ...message };
685+
delete messageToUpdate.i18n;
671686
await this.chatClientService.chatClient.updateMessage(
672-
message as any as UpdatedMessage<T>
687+
messageToUpdate as any as UpdatedMessage<T>
673688
);
674689
}
675690

@@ -1437,18 +1452,52 @@ export class ChannelService<
14371452
this.isStreamMessage(message) &&
14381453
this.isFormatMessageResponse(message)
14391454
) {
1455+
if (message.quoted_message) {
1456+
message.quoted_message.translation = getMessageTranslation(
1457+
message.quoted_message,
1458+
channel,
1459+
this.chatClientService.chatClient.user
1460+
);
1461+
}
1462+
message.translation = getMessageTranslation(
1463+
message,
1464+
channel,
1465+
this.chatClientService.chatClient.user
1466+
);
14401467
return message;
1441-
} else if (this.isFormatMessageResponse(message)) {
1442-
return {
1443-
...message,
1444-
readBy: isThreadMessage ? [] : getReadBy(message, channel),
1445-
};
14461468
} else {
1447-
const formatMessage = this.formatMessage(message);
1448-
return {
1449-
...formatMessage,
1450-
readBy: isThreadMessage ? [] : getReadBy(formatMessage, channel),
1451-
};
1469+
if (message.quoted_message) {
1470+
message.quoted_message = {
1471+
...message.quoted_message,
1472+
translation: getMessageTranslation(
1473+
message.quoted_message,
1474+
channel,
1475+
this.chatClientService.chatClient.user
1476+
),
1477+
};
1478+
}
1479+
if (this.isFormatMessageResponse(message)) {
1480+
return {
1481+
...message,
1482+
readBy: isThreadMessage ? [] : getReadBy(message, channel),
1483+
translation: getMessageTranslation(
1484+
message,
1485+
channel,
1486+
this.chatClientService.chatClient.user
1487+
),
1488+
};
1489+
} else {
1490+
const formatMessage = this.formatMessage(message);
1491+
return {
1492+
...formatMessage,
1493+
readBy: isThreadMessage ? [] : getReadBy(formatMessage, channel),
1494+
translation: getMessageTranslation(
1495+
message,
1496+
channel,
1497+
this.chatClientService.chatClient.user
1498+
),
1499+
};
1500+
}
14521501
}
14531502
}
14541503

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {
2+
Channel,
3+
FormatMessageResponse,
4+
MessageResponse,
5+
TranslationLanguages,
6+
User,
7+
} from 'stream-chat';
8+
import { DefaultStreamChatGenerics, StreamMessage } from './types';
9+
10+
export const getMessageTranslation = <
11+
T extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
12+
>(
13+
message?: StreamMessage | MessageResponse | FormatMessageResponse,
14+
channel?: Channel<T>,
15+
user?: User
16+
) => {
17+
const language =
18+
user?.language ||
19+
(channel?.data?.auto_translation_language as TranslationLanguages);
20+
if (language && message?.i18n && message?.user?.id !== user?.id) {
21+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
22+
return message.i18n[`${language}_text` as `${TranslationLanguages}_text`];
23+
} else {
24+
return undefined;
25+
}
26+
};

projects/stream-chat-angular/src/lib/message-actions-box/message-actions-box.component.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ describe('MessageActionsBoxComponent', () => {
183183
it(`shouldn't disable quote action, if message already has a quoted message`, () => {
184184
component.message = {
185185
...component.message!,
186-
quoted_message: mockMessage() as any as MessageResponseBase,
186+
quoted_message:
187+
mockMessage() as any as MessageResponseBase<DefaultStreamChatGenerics>,
187188
};
188189
component.enabledActions = ['quote-message'];
189190
component.ngOnChanges({

0 commit comments

Comments
 (0)