Skip to content

Commit

Permalink
feat: Auto-enable autotranslate (#30370)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriellsh authored Sep 29, 2023
1 parent 6733398 commit 1642bad
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/large-pandas-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": minor
---

New setting to automatically enable autotranslate when joining rooms
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { IUser } from '@rocket.chat/core-typings';
import { Subscriptions, Rooms } from '@rocket.chat/models';

import { callbacks } from '../../../../lib/callbacks';
import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig';

export const addUserToDefaultChannels = async function (user: IUser, silenced?: boolean): Promise<void> {
await callbacks.run('beforeJoinDefaultChannels', user);
Expand All @@ -11,6 +12,7 @@ export const addUserToDefaultChannels = async function (user: IUser, silenced?:
}).toArray();
for await (const room of defaultRooms) {
if (!(await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id, { projection: { _id: 1 } }))) {
const autoTranslateConfig = await getSubscriptionAutotranslateDefaultConfig(user);
// Add a subscription to this user
await Subscriptions.createWithRoomAndUser(room, user, {
ts: new Date(),
Expand All @@ -20,6 +22,7 @@ export const addUserToDefaultChannels = async function (user: IUser, silenced?:
userMentions: 1,
groupMentions: 0,
...(room.favorite && { f: true }),
...autoTranslateConfig,
});

// Insert user joined message
Expand Down
6 changes: 5 additions & 1 deletion apps/meteor/app/lib/server/functions/addUserToRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Meteor } from 'meteor/meteor';
import { RoomMemberActions } from '../../../../definition/IRoomTypeConfig';
import { AppEvents, Apps } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig';
import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator';

export const addUserToRoom = async function (
Expand All @@ -24,7 +25,7 @@ export const addUserToRoom = async function (
});
}

const userToBeAdded = typeof user !== 'string' ? user : await Users.findOneByUsername(user.replace('@', ''));
const userToBeAdded = typeof user === 'string' ? await Users.findOneByUsername(user.replace('@', '')) : await Users.findOneById(user._id);
const roomDirectives = roomCoordinator.getRoomDirectives(room.t);

if (!userToBeAdded) {
Expand Down Expand Up @@ -70,13 +71,16 @@ export const addUserToRoom = async function (
await callbacks.run('beforeJoinRoom', userToBeAdded, room);
}

const autoTranslateConfig = await getSubscriptionAutotranslateDefaultConfig(userToBeAdded);

await Subscriptions.createWithRoomAndUser(room, userToBeAdded as IUser, {
ts: now,
open: true,
alert: true,
unread: 1,
userMentions: 1,
groupMentions: 0,
...autoTranslateConfig,
});

if (!userToBeAdded.username) {
Expand Down
6 changes: 5 additions & 1 deletion apps/meteor/app/lib/server/functions/createRoom.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable complexity */
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
import { Message, Team } from '@rocket.chat/core-services';
import type { ICreateRoomParams, ISubscriptionExtraData } from '@rocket.chat/core-services';
Expand All @@ -8,6 +9,7 @@ import { Meteor } from 'meteor/meteor';
import { Apps } from '../../../../ee/server/apps/orchestrator';
import { callbacks } from '../../../../lib/callbacks';
import { beforeCreateRoomCallback } from '../../../../lib/callbacks/beforeCreateRoomCallback';
import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig';
import { addUserRolesAsync } from '../../../../server/lib/roles/addUserRoles';
import { getValidRoomName } from '../../../utils/server/lib/getValidRoomName';
import { createDirectRoom } from './createDirectRoom';
Expand Down Expand Up @@ -178,7 +180,9 @@ export const createRoom = async <T extends RoomType>(
extra.ls = now;
}

await Subscriptions.createWithRoomAndUser(room, member, extra);
const autoTranslateConfig = await getSubscriptionAutotranslateDefaultConfig(member);

await Subscriptions.createWithRoomAndUser(room, member, { ...extra, ...autoTranslateConfig });
}
}

Expand Down
2 changes: 2 additions & 0 deletions apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,8 @@
"AutoTranslate_DeepL": "DeepL",
"AutoTranslate_Enabled": "Enable Auto-Translate",
"AutoTranslate_Enabled_Description": "Enabling auto-translation will allow people with the `auto-translate` permission to have all messages automatically translated into their selected language. Fees may apply.",
"AutoTranslate_AutoEnableOnJoinRoom": "Auto-Translate for non-default language members",
"AutoTranslate_AutoEnableOnJoinRoom_Description": "If enabled, whenever a user with a language preference different than the workspace default joins a room, it will be automatically translated for them.",
"AutoTranslate_Google": "Google",
"AutoTranslate_Microsoft": "Microsoft",
"AutoTranslate_Microsoft_API_Key": "Ocp-Apim-Subscription-Key",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { IUser } from '@rocket.chat/core-typings';
import { Settings } from '@rocket.chat/models';

export const getSubscriptionAutotranslateDefaultConfig = async (
user: IUser,
): Promise<
| {
autoTranslate: boolean;
autoTranslateLanguage: string;
}
| undefined
> => {
const [autoEnableSetting, languageSetting] = await Promise.all([
Settings.findOneById('AutoTranslate_AutoEnableOnJoinRoom'),
Settings.findOneById('Language'),
]);
const { language: userLanguage } = user.settings?.preferences || {};

if (!autoEnableSetting?.value) {
return;
}

if (!userLanguage || userLanguage === 'default' || languageSetting?.value === userLanguage) {
return;
}

return { autoTranslate: true, autoTranslateLanguage: userLanguage };
};
3 changes: 3 additions & 0 deletions apps/meteor/server/methods/addAllUserToRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../app/authorization/server/functions/hasPermission';
import { settings } from '../../app/settings/server';
import { callbacks } from '../../lib/callbacks';
import { getSubscriptionAutotranslateDefaultConfig } from '../lib/getSubscriptionAutotranslateDefaultConfig';

declare module '@rocket.chat/ui-contexts' {
// eslint-disable-next-line @typescript-eslint/naming-convention
Expand Down Expand Up @@ -55,13 +56,15 @@ Meteor.methods<ServerMethods>({
continue;
}
await callbacks.run('beforeJoinRoom', user, room);
const autoTranslateConfig = await getSubscriptionAutotranslateDefaultConfig(user);
await Subscriptions.createWithRoomAndUser(room, user, {
ts: now,
open: true,
alert: true,
unread: 1,
userMentions: 1,
groupMentions: 0,
...autoTranslateConfig,
});
await Message.saveSystemMessage('uj', rid, user.username || '', user, { ts: now });
await callbacks.run('afterJoinRoom', user, room);
Expand Down
8 changes: 8 additions & 0 deletions apps/meteor/server/settings/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ export const createMessageSettings = () =>
public: true,
});

await this.add('AutoTranslate_AutoEnableOnJoinRoom', false, {
type: 'boolean',
group: 'Message',
section: 'AutoTranslate',
public: true,
enableQuery: [{ _id: 'AutoTranslate_Enabled', value: true }],
});

await this.add('AutoTranslate_ServiceProvider', 'google-translate', {
type: 'select',
group: 'Message',
Expand Down
130 changes: 129 additions & 1 deletion apps/meteor/tests/end-to-end/api/00-autotranslate.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { expect } from 'chai';
import { before, describe, it } from 'mocha';
import { before, describe, after, it } from 'mocha';

import { getCredentials, api, request, credentials } from '../../data/api-data.js';
import { sendSimpleMessage } from '../../data/chat.helper';
import { updatePermission, updateSetting } from '../../data/permissions.helper';
import { createRoom } from '../../data/rooms.helper';
import { password } from '../../data/user';
import { createUser, login } from '../../data/users.helper.js';

describe('AutoTranslate', function () {
this.retries(0);
Expand Down Expand Up @@ -314,5 +317,130 @@ describe('AutoTranslate', function () {
.end(done);
});
});
describe('Autoenable setting', () => {
let userA;
let userB;
let credA;
let credB;
let channel;

const createChannel = async (members, cred) =>
(await createRoom({ type: 'c', members, name: `channel-test-${Date.now()}`, credentials: cred })).body.channel;

const setLanguagePref = async (language, cred) => {
await request
.post(api('users.setPreferences'))
.set(cred)
.send({ data: { language } })
.expect(200)
.expect('Content-Type', 'application/json')
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
};

const getSub = async (roomId, cred) =>
(
await request
.get(api('subscriptions.getOne'))
.set(cred)
.query({
roomId,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription').and.to.be.an('object');
})
).body.subscription;

before(async () => {
await updateSetting('AutoTranslate_Enabled', true);
await updateSetting('AutoTranslate_AutoEnableOnJoinRoom', true);
await updateSetting('Language', 'pt-BR');

channel = await createChannel();
userA = await createUser();
userB = await createUser();

credA = await login(userA.username, password);
credB = await login(userB.username, password);

await setLanguagePref('en', credB);
});

after(async () => {
await updateSetting('AutoTranslate_AutoEnableOnJoinRoom', false);
await updateSetting('AutoTranslate_Enabled', false);
await updateSetting('Language', '');
});

it("should do nothing if the user hasn't changed his language preference", async () => {
const sub = await getSub(channel._id, credentials);
expect(sub).to.not.have.property('autoTranslate');
expect(sub).to.not.have.property('autoTranslateLanguage');
});

it("should do nothing if the user changed his language preference to be the same as the server's", async () => {
await setLanguagePref('pt-BR', credA);

const channel = await createChannel(undefined, credA);
const sub = await getSub(channel._id, credA);
expect(sub).to.not.have.property('autoTranslate');
expect(sub).to.not.have.property('autoTranslateLanguage');
});

it('should enable autotranslate with the correct language when creating a new room', async () => {
await setLanguagePref('en', credA);

const channel = await createChannel(undefined, credA);
const sub = await getSub(channel._id, credA);
expect(sub).to.have.property('autoTranslate');
expect(sub).to.have.property('autoTranslateLanguage').and.to.be.equal('en');
});

it('should enable autotranslate for all the members added to the room upon creation', async () => {
const channel = await createChannel([userA.username, userB.username]);
const subA = await getSub(channel._id, credA);
expect(subA).to.have.property('autoTranslate');
expect(subA).to.have.property('autoTranslateLanguage').and.to.be.equal('en');

const subB = await getSub(channel._id, credB);
expect(subB).to.have.property('autoTranslate');
expect(subB).to.have.property('autoTranslateLanguage').and.to.be.equal('en');
});

it('should enable autotranslate with the correct language when joining a room', async () => {
await request
.post(api('channels.join'))
.set(credA)
.send({
roomId: channel._id,
})
.expect('Content-Type', 'application/json')
.expect(200);

const sub = await getSub(channel._id, credA);
expect(sub).to.have.property('autoTranslate');
expect(sub).to.have.property('autoTranslateLanguage').and.to.be.equal('en');
});

it('should enable autotranslate with the correct language when added to a room', async () => {
await request
.post(api('channels.invite'))
.set(credentials)
.send({
roomId: channel._id,
userId: userB._id,
})
.expect('Content-Type', 'application/json')
.expect(200);

const sub = await getSub(channel._id, credB);
expect(sub).to.have.property('autoTranslate');
expect(sub).to.have.property('autoTranslateLanguage').and.to.be.equal('en');
});
});
});
});

0 comments on commit 1642bad

Please sign in to comment.