Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 39 additions & 9 deletions app/containers/MessageComposer/hooks/useAutocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,47 @@ export const useAutocomplete = ({
if (type === '/') {
const db = database.active;
const commandsCollection = db.get('slash_commands');
const appTranslationsCollection = db.get('app_translations');
const likeString = sanitizeLikeString(text);
const commands = await (
await commandsCollection.query(Q.where('id', Q.like(`${likeString}%`))).fetch()
).map(command => ({
id: command.id,
title: command.id,
subtitle: command.description,
type
}));
setItems(commands);

const rawCommands = await commandsCollection.query(Q.where('id', Q.like(`${likeString}%`))).fetch();

const commands = await Promise.all(
rawCommands.map(async command => {
let subtitle = '';
const { description } = command;

if (!description) {
// no description at all — leave empty
subtitle = '';
} else if (command.appId) {
const appLang = I18n.currentLocale().split('-')[0];

// app translation key — look up in WatermelonDB
const translationRecords = await appTranslationsCollection
.query(Q.where('key', description), Q.where('language', appLang))
.fetch();

if (translationRecords.length > 0) {
subtitle = (translationRecords[0] as any).value;
} else {
// not in DB yet — fallback to readable form
subtitle = description.split('.').pop()?.replace(/_/g, ' ') ?? description;
}
} else {
subtitle = description;
}

return {
id: command.id,
title: command.id,
subtitle,
type
};
})
);

setItems(commands);
if (commands.length > 0) {
updateAutocompleteVisible(true);
accessibilityFocusOnInput();
Expand Down
8 changes: 8 additions & 0 deletions app/definitions/rest/v1/appTranslations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type AppsTranslationsEndpoints = {
'apps.translations': {
GET: (params: { language?: string }) => {
language: string;
translations: { [key: string]: string };
};
};
};
4 changes: 3 additions & 1 deletion app/definitions/rest/v1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { type PushEndpoints } from './push';
import { type DirectoryEndpoint } from './directory';
import { type AutoTranslateEndpoints } from './autotranslate';
import { type ModerationEndpoints } from './moderation';
import { type AppsTranslationsEndpoints } from './appTranslations';

export type Endpoints = ChannelsEndpoints &
ChatEndpoints &
Expand All @@ -44,4 +45,5 @@ export type Endpoints = ChannelsEndpoints &
PushEndpoints &
DirectoryEndpoint &
AutoTranslateEndpoints &
ModerationEndpoints;
ModerationEndpoints &
AppsTranslationsEndpoints;
4 changes: 3 additions & 1 deletion app/lib/database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import appSchema from './schema/app';
import migrations from './model/migrations';
import serversMigrations from './model/servers/migrations';
import { type TAppDatabase, type TServerDatabase } from './interfaces';
import AppTranslation from './model/AppTranslation';

if (__DEV__) {
console.log(appGroupPath);
Expand Down Expand Up @@ -60,7 +61,8 @@ export const getDatabase = (database = ''): Database => {
Role,
Permission,
SlashCommand,
User
User,
AppTranslation
]
});
};
Expand Down
10 changes: 10 additions & 0 deletions app/lib/database/model/AppTranslation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Model } from '@nozbe/watermelondb';
import { field } from '@nozbe/watermelondb/decorators';

export default class AppTranslation extends Model {
static table = 'app_translations';

@field('key') key!: string;
@field('value') value!: string;
@field('language') language!: string;
}
13 changes: 13 additions & 0 deletions app/lib/database/model/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,19 @@ export default schemaMigrations({
]
})
]
},
{
toVersion: 29,
steps: [
createTable({
name: 'app_translations',
columns: [
{ name: 'key', type: 'string', isIndexed: true },
{ name: 'value', type: 'string' },
{ name: 'language', type: 'string', isIndexed: true }
]
})
]
}
]
});
10 changes: 9 additions & 1 deletion app/lib/database/schema/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { appSchema, tableSchema } from '@nozbe/watermelondb';

export default appSchema({
version: 28,
version: 29,
tables: [
tableSchema({
name: 'subscriptions',
Expand Down Expand Up @@ -285,6 +285,14 @@ export default appSchema({
{ name: 'username', type: 'string', isIndexed: true },
{ name: 'avatar_etag', type: 'string', isOptional: true }
]
}),
tableSchema({
name: 'app_translations',
columns: [
{ name: 'key', type: 'string', isIndexed: true },
{ name: 'value', type: 'string' },
{ name: 'language', type: 'string', isIndexed: true }
]
})
]
});
41 changes: 41 additions & 0 deletions app/lib/methods/getAppTranslations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
import { Q } from '@nozbe/watermelondb';

import database from '../database';
import log from './helpers/log';
import protectedFunction from './helpers/protectedFunction';
import sdk from '../services/sdk';

export async function getAppTranslations(language = 'en'): Promise<void> {
try {
const db = database.active;

const result = await sdk.get('apps.translations', { language });

if (!result?.success || !result.translations) {
return;
}

await db.write(async () => {
const collection = db.get('app_translations');

const existing = await collection.query(Q.where('language', result.language)).fetch();
const toDelete = existing.map((r: any) => r.prepareDestroyPermanently());

const toCreate = Object.entries(result.translations).map(([key, value]) =>
collection.prepareCreate(
protectedFunction((r: any) => {
r._raw = sanitizedRaw({ id: `${result.language}_${key}` }, collection.schema);
r.key = key;
r.value = value as string;
r.language = result.language;
})
)
);

await db.batch(...toDelete, ...toCreate);
});
} catch (e) {
log(e);
}
}
1 change: 1 addition & 0 deletions app/lib/methods/getSlashCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function getSlashCommands() {
if (!result.success) {
return resolve();
}

// @ts-ignore
const { commands } = result;
if (commands && commands.length) {
Expand Down
11 changes: 11 additions & 0 deletions app/sagas/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import appNavigation from '../lib/navigation/appNavigation';
import { showActionSheetRef } from '../containers/ActionSheet';
import { SupportedVersionsWarning } from '../containers/SupportedVersions';
import { isIOS } from '../lib/methods/helpers';
import { getAppTranslations } from '../lib/methods/getAppTranslations';

const getServer = state => state.server.server;
const loginWithPasswordCall = args => loginWithPassword(args);
Expand Down Expand Up @@ -184,6 +185,15 @@ const fetchSlashCommandsFork = function* fetchSlashCommandsFork() {
}
};

const fetchAppTranslationsFork = function* fetchAppTranslationsFork() {
try {
const appLang = I18n.currentLocale().split('-')[0];
yield getAppTranslations(appLang);
} catch (e) {
log(e);
}
};

const registerPushTokenFork = function* registerPushTokenFork() {
try {
yield registerPushToken();
Expand Down Expand Up @@ -251,6 +261,7 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
yield fork(fetchCustomEmojisFork);
yield fork(fetchRolesFork);
yield fork(fetchSlashCommandsFork);
yield fork(fetchAppTranslationsFork);
yield fork(registerPushTokenFork);
yield fork(fetchUsersPresenceFork);
yield fork(fetchEnterpriseModulesFork, { user });
Expand Down
4 changes: 4 additions & 0 deletions app/views/LanguageView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { type SettingsStackParamList } from '../../stacks/types';
import { showErrorAlert } from '../../lib/methods/helpers/info';
import log, { events, logEvent } from '../../lib/methods/helpers/log';
import { saveUserPreferences } from '../../lib/services/restApi';
import { getAppTranslations } from '../../lib/methods/getAppTranslations';

const LanguageView = () => {
const { languageDefault, id } = useAppSelector(state => ({
Expand Down Expand Up @@ -81,6 +82,9 @@ const LanguageView = () => {
logEvent(events.LANG_SET_LANGUAGE_F);
}
});

const appLang = (params.language || 'en').split('-')[0];
await getAppTranslations(appLang);
} catch (e) {
logEvent(events.LANG_SET_LANGUAGE_F);
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_preferences') }));
Expand Down