diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 7a054b1e2..c874fc15f 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -30,7 +30,11 @@
"adminRemoveAsAdmin": "Remove as Admin",
"adminRemoveCommunityNone": "There are no Admins in this Community.",
"adminRemoveFailed": "Failed to remove {name} as Admin.",
+ "adminRemoveFailedMultiple": "Failed to remove {name} and {count} others as Admin.",
+ "adminRemoveFailedOther": "Failed to remove {name} and {other_name} as Admin.",
"adminRemovedUser": "{name} was removed as Admin.",
+ "adminRemovedUserMultiple": "{name} and {count} others were removed as Admin.",
+ "adminRemovedUserOther": "{name} and {other_name} were removed as Admin.",
"adminSendingPromotion": "Sending admin promotion",
"adminSettings": "Admin Settings",
"adminTwoPromotedToAdmin": "{name} and {other_name} were promoted to Admin.",
@@ -67,6 +71,7 @@
"attachmentsDownload": "Download Attachment",
"attachmentsDuration": "Duration:",
"attachmentsErrorLoad": "Error attaching file",
+ "attachmentsErrorMediaSelection": "Failed to select attachment",
"attachmentsErrorNoApp": "Can't find an app to select media.",
"attachmentsErrorNotSupported": "This file type is not supported.",
"attachmentsErrorNumber": "Unable to send more than 32 image and video files at once.",
@@ -143,7 +148,7 @@
"callsPermissionsRequiredDescription": "You can enable the \"Voice and Video Calls\" permission in Privacy Settings.",
"callsReconnecting": "Reconnecting…",
"callsRinging": "Ringing...",
- "callsSessionCall": "Session Call",
+ "callsSessionCall": "{app_name} Call",
"callsSettings": "Calls (Beta)",
"callsVoiceAndVideo": "Voice and Video Calls",
"callsVoiceAndVideoBeta": "Voice and Video Calls (Beta)",
@@ -243,7 +248,7 @@
"create": "Create",
"cut": "Cut",
"databaseErrorGeneric": "A database error occurred.
Export your application logs to share for troubleshooting. If this is unsuccessful, reinstall {app_name} and restore your account.
Warning: This will result in loss of all messages, attachments, and account data older than two weeks.",
- "databaseErrorTimeout": "We've noticed {app_name} is taking a long time to start.
You can continue to wait, export your device logs to share for troubleshooting, or try restarting Session.",
+ "databaseErrorTimeout": "We've noticed {app_name} is taking a long time to start.
You can continue to wait, export your device logs to share for troubleshooting, or try restarting {app_name}.",
"databaseErrorUpdate": "Your app database is incompatible with this version of {app_name}. Reinstall the app and restore your account to generate a new database and continue using {app_name}.
Warning: This will result in the loss of all messages and attachments older than two weeks.",
"databaseOptimizing": "Optimizing Database",
"debugLog": "Debug Log",
@@ -261,6 +266,8 @@
"deleteAfterLegacyDisappearingMessagesLegacy": "Legacy",
"deleteAfterLegacyDisappearingMessagesOriginal": "Original version of disappearing messages.",
"deleteAfterLegacyDisappearingMessagesTheyChangedTimer": "{name} set the disappearing message timer to {time}",
+ "deleteAfterLegacyGroupsGroupCreation": "Please wait while the group is created...",
+ "deleteAfterLegacyGroupsGroupUpdateErrorTitle": "Failed to Update Group",
"deleteMessage": "Delete Message",
"deleteMessageConfirm": "Are you sure you want to delete this message?",
"deleteMessageDeleted": "Message deleted",
@@ -325,27 +332,27 @@
"downloading": "Downloading...",
"draft": "Draft",
"edit": "Edit",
- "emojiAndSymbols": "Emoji & Symbols",
+ "emojiAndSymbols": "Emoji and Symbols",
"emojiCategoryActivities": "Activities",
- "emojiCategoryAnimals": "Animals & Nature",
+ "emojiCategoryAnimals": "Animals and Nature",
"emojiCategoryFlags": "Flags",
- "emojiCategoryFood": "Food & Drink",
+ "emojiCategoryFood": "Food and Drink",
"emojiCategoryObjects": "Objects",
"emojiCategoryRecentlyUsed": "Recently Used",
- "emojiCategorySmileys": "Smileys & People",
+ "emojiCategorySmileys": "Smileys and People",
"emojiCategorySymbols": "Symbols",
- "emojiCategoryTravel": "Travel & Places",
+ "emojiCategoryTravel": "Travel and Places",
"emojiReactsClearAll": "Are you sure you want to clear all {emoji}?",
"emojiReactsCoolDown": "Slow down! You've sent too many emoji reacts. Try again soon",
"emojiReactsCountOthers": "{count, plural, one {And # other has reacted {emoji} to this message.} other {And # others have reacted {emoji} to this message.}}",
"emojiReactsHoverNameDesktop": "{name} reacted with ",
- "emojiReactsHoverTwoNameDesktop": "{name} & {other_name} reacted with ",
+ "emojiReactsHoverTwoNameDesktop": "{name} and {other_name} reacted with ",
"emojiReactsHoverTwoNameMultipleDesktop": "{name}, {other_name} and {count} others reacted with ",
"emojiReactsHoverTwoNameOneDesktop": "{name}, {other_name} and 1 other reacted with ",
"emojiReactsHoverYouDesktop": "You reacted with ",
- "emojiReactsHoverYouNameDesktop": "You & {name} reacted with ",
- "emojiReactsHoverYouNameMultipleDesktop": "You, {name} & {count} others reacted with ",
- "emojiReactsHoverYouNameOneDesktop": "You, {name} & 1 other reacted with ",
+ "emojiReactsHoverYouNameDesktop": "You and {name} reacted with ",
+ "emojiReactsHoverYouNameMultipleDesktop": "You, {name} and {count} others reacted with ",
+ "emojiReactsHoverYouNameOneDesktop": "You, {name} and 1 other reacted with ",
"emojiReactsNotification": "Reacted to your message {emoji}",
"enable": "Enable",
"errorConnection": "Please check your internet connection and try again.",
@@ -381,8 +388,10 @@
"groupInviteSending": "Sending invite",
"groupInviteSent": "Invite sent",
"groupInviteSuccessful": "Group invite successful",
- "groupInviteVersion": "Users must have version {version} or higher to receive invitations",
+ "groupInviteVersion": "Users must have the latest release to receive invitations",
"groupInviteYou": "You were invited to join the group.",
+ "groupInviteYouAndMoreNew": "You and {count} others were invited to join the group.",
+ "groupInviteYouAndOtherNew": "You and {other_name} were invited to join the group.",
"groupLeave": "Leave Group",
"groupLeaveDescription": "Are you sure you want to leave {group_name}?",
"groupLeaveDescriptionAdmin": "Are you sure you want to leave {group_name}? This will deactivate the group for all members.",
@@ -392,7 +401,7 @@
"groupMemberLeftMore": "{name} and {count} others left the group.",
"groupMemberLeftTwo": "{name} and {other_name} left the group.",
"groupMemberMoreNew": "{name} and {count} others joined the group.",
- "groupMemberNew": "{name} joined the group.",
+ "groupMemberNew": "{name} was invited to join the group.",
"groupMemberNewHistory": "{name} was invited to join the group. Chat history was shared.",
"groupMemberNewHistoryMultiple": "{name} and {count} others were invited to join the group. Chat history was shared.",
"groupMemberNewHistoryTwo": "{name} and {other_name} were invited to join the group. Chat history was shared.",
@@ -401,12 +410,11 @@
"groupMemberNewYouHistory": " {name} was invited to join the group. Chat history was shared.",
"groupMemberNewYouHistoryMultiple": "You and {count} others were invited to join the group. Chat history was shared.",
"groupMemberNewYouHistoryTwo": "You and {name} were invited to join the group. Chat history was shared.",
- "groupMemberNewYouMultiple": "You and {count} others were invited to join the group.",
- "groupMemberNewYouTwo": "You and {name} were invited to join the group.",
+ "groupMemberNewYouMultiple": "You and {count} others joined the group.",
+ "groupMemberNewYouOther": "You and {other_name} joined the group.",
"groupMemberTwoNew": "{name} and {other_name} joined the group.",
- "groupMemberYouAndMoreNew": "You and {count} others joined the group.",
- "groupMemberYouAndOtherNew": "You and {other_name} joined the group.",
"groupMemberYouLeft": "You left the group.",
+ "groupMemberYouNew": "You joined the group.",
"groupMembers": "Group Members",
"groupMembersNone": "There are no other members in this group.",
"groupName": "Group Name",
@@ -582,8 +590,8 @@
"onboardingAccountCreate": "Create account",
"onboardingAccountCreated": "Account Created",
"onboardingAccountExists": "I have an account",
- "onboardingBackAccountCreation": "You cannot go back further. In order to cancel your account creation, Session needs to quit.",
- "onboardingBackLoadAccount": "You cannot go back further. In order to stop loading your account, Session needs to quit.",
+ "onboardingBackAccountCreation": "You cannot go back further. In order to cancel your account creation, {app_name} needs to quit.",
+ "onboardingBackLoadAccount": "You cannot go back further. In order to stop loading your account, {app_name} needs to quit.",
"onboardingBubbleCreatingAnAccountIsEasy": "Creating an account is instant, free, and anonymous ",
"onboardingBubbleNoPhoneNumber": "You don't even need a phone number to sign up.",
"onboardingBubblePrivacyInYourPocket": "Privacy in your pocket.",
@@ -670,6 +678,7 @@
"recoveryPasswordBannerTitle": "Save your recovery password",
"recoveryPasswordDescription": "Use your recovery password to load your account on new devices.
Your account cannot be recovered without your recovery password. Make sure it's stored somewhere safe and secure — and don't share it with anyone.",
"recoveryPasswordEnter": "Enter your recovery password",
+ "recoveryPasswordErrorLoad": "An error occurred when trying to load your recovery password.
Please export your logs, then upload the file though Session's Help Desk to help resolve this issue.",
"recoveryPasswordErrorMessageGeneric": "Please check your recovery password and try again.",
"recoveryPasswordErrorMessageIncorrect": "Some of the words in your Recovery Password are incorrect. Please check and try again.",
"recoveryPasswordErrorMessageShort": "The Recovery Password you entered is not long enough. Please check and try again.",
@@ -729,7 +738,7 @@
"set": "Set",
"settingsRestartDescription": "You must restart {app_name} to apply your new settings.",
"share": "Share",
- "shareAccountIdDescription": "Invite your friend to chat with you on Session by sharing your Account ID with them.",
+ "shareAccountIdDescription": "Invite your friend to chat with you on {app_name} by sharing your Account ID with them.",
"shareAccountIdDescriptionCopied": "Share with your friends wherever you usually speak with them — then move the conversation here.",
"shareExtensionDatabaseError": "There is an issue opening the database. Please restart the app and try again.",
"shareToSession": "Share to {app_Name}",
@@ -771,4 +780,4 @@
"window": "Window",
"yes": "Yes",
"you": "You"
-}
+}
\ No newline at end of file
diff --git a/ts/components/basic/SessionHTMLRenderer.tsx b/ts/components/basic/SessionHTMLRenderer.tsx
index 390857523..073ada1c3 100644
--- a/ts/components/basic/SessionHTMLRenderer.tsx
+++ b/ts/components/basic/SessionHTMLRenderer.tsx
@@ -17,7 +17,6 @@ export const SessionHtmlRenderer = ({ tag = 'div', key, html, className }: Recei
return createElement(tag, {
key,
className,
-
dangerouslySetInnerHTML: { __html: clean },
});
};
diff --git a/ts/components/conversation/SessionConversation.tsx b/ts/components/conversation/SessionConversation.tsx
index f4e5d9f46..9febbc841 100644
--- a/ts/components/conversation/SessionConversation.tsx
+++ b/ts/components/conversation/SessionConversation.tsx
@@ -398,7 +398,7 @@ export class SessionConversation extends Component {
});
if (blob.blob.size > MAX_ATTACHMENT_FILESIZE_BYTES) {
- ToastUtils.pushFileSizeErrorAsByte(MAX_ATTACHMENT_FILESIZE_BYTES);
+ ToastUtils.pushFileSizeErrorAsByte();
return;
}
} catch (error) {
diff --git a/ts/components/conversation/SessionRecording.tsx b/ts/components/conversation/SessionRecording.tsx
index f6f5073b1..82ac335f7 100644
--- a/ts/components/conversation/SessionRecording.tsx
+++ b/ts/components/conversation/SessionRecording.tsx
@@ -291,7 +291,7 @@ export class SessionRecording extends Component {
// Is the audio file > attachment filesize limit
if (this.audioBlobMp3.size > MAX_ATTACHMENT_FILESIZE_BYTES) {
- ToastUtils.pushFileSizeErrorAsByte(MAX_ATTACHMENT_FILESIZE_BYTES);
+ ToastUtils.pushFileSizeErrorAsByte();
return;
}
diff --git a/ts/components/dialog/ModeratorsAddDialog.tsx b/ts/components/dialog/ModeratorsAddDialog.tsx
index 4b774c8ec..1c285feb6 100644
--- a/ts/components/dialog/ModeratorsAddDialog.tsx
+++ b/ts/components/dialog/ModeratorsAddDialog.tsx
@@ -50,8 +50,11 @@ export const AddModeratorsDialog = (props: Props) => {
ToastUtils.pushFailedToAddAsModerator();
} else {
+ const userDisplayName =
+ getConversationController().get(pubkey.key)?.getNicknameOrRealUsernameOrPlaceholder() ||
+ window.i18n('unknown');
window?.log?.info(`${pubkey.key} added as moderator...`);
- ToastUtils.pushUserAddedToModerators();
+ ToastUtils.pushUserAddedToModerators(userDisplayName);
// clear input box
setInputBoxValue('');
diff --git a/ts/components/dialog/ModeratorsRemoveDialog.tsx b/ts/components/dialog/ModeratorsRemoveDialog.tsx
index 9e413fdcc..64d01ca58 100644
--- a/ts/components/dialog/ModeratorsRemoveDialog.tsx
+++ b/ts/components/dialog/ModeratorsRemoveDialog.tsx
@@ -25,22 +25,27 @@ async function removeMods(convoId: string, modsToRemove: Array) {
return false;
}
window?.log?.info(`asked to remove moderators: ${modsToRemove}`);
-
+ const modsToRemovePubkey = compact(modsToRemove.map(m => PubKey.from(m)));
+ const modsToRemoveNames = modsToRemovePubkey.map(
+ m =>
+ getConversationController().get(m.key)?.getNicknameOrRealUsernameOrPlaceholder() ||
+ window.i18n('unknown')
+ );
try {
const convo = getConversationController().get(convoId);
const roomInfos = convo.toOpenGroupV2();
- const modsToRemovePubkey = compact(modsToRemove.map(m => PubKey.from(m)));
+
const res = await sogsV3RemoveAdmins(modsToRemovePubkey, roomInfos);
if (!res) {
window?.log?.warn('failed to remove moderators:', res);
- ToastUtils.pushFailedToRemoveFromModerator();
+ ToastUtils.pushFailedToRemoveFromModerator(modsToRemoveNames);
return false;
}
window?.log?.info(`${modsToRemove} removed from moderators...`);
- ToastUtils.pushUserRemovedFromModerators();
+ ToastUtils.pushUserRemovedFromModerators(modsToRemoveNames);
return true;
} catch (e) {
window?.log?.error('Got error while removing moderator:', e);
diff --git a/ts/interactions/messageInteractions.ts b/ts/interactions/messageInteractions.ts
index 56fd75d0d..7da1ec4b4 100644
--- a/ts/interactions/messageInteractions.ts
+++ b/ts/interactions/messageInteractions.ts
@@ -78,10 +78,10 @@ export async function removeSenderFromModerator(sender: string, convoId: string)
if (!res) {
window?.log?.warn('failed to remove moderator:', res);
- ToastUtils.pushFailedToRemoveFromModerator(userDisplayName);
+ ToastUtils.pushFailedToRemoveFromModerator([userDisplayName]);
} else {
window?.log?.info(`${pubKeyToRemove.key} removed from moderators...`);
- ToastUtils.pushUserRemovedFromModerators(userDisplayName);
+ ToastUtils.pushUserRemovedFromModerators([userDisplayName]);
}
} catch (e) {
window?.log?.error('Got error while removing moderator:', e);
diff --git a/ts/models/groupUpdate.ts b/ts/models/groupUpdate.ts
index ae5de957a..4f5a87aea 100644
--- a/ts/models/groupUpdate.ts
+++ b/ts/models/groupUpdate.ts
@@ -89,9 +89,9 @@ export function getJoinedGroupUpdateChangeStr(
case 0:
return getString('groupMemberNew', { name: window.i18n('you') });
case 1:
- return getString('groupMemberYouAndOtherNew', { other_name: othersNames[0] });
+ return getString('groupMemberNewYouOther', { other_name: othersNames[0] });
default:
- return getString('groupMemberYouAndMoreNew', { count: othersNames.length });
+ return getString('groupMemberNewYouMultiple', { count: othersNames.length });
}
}
switch (others.length) {
diff --git a/ts/session/utils/Toast.tsx b/ts/session/utils/Toast.tsx
index 7b7596054..c40171a6d 100644
--- a/ts/session/utils/Toast.tsx
+++ b/ts/session/utils/Toast.tsx
@@ -35,6 +35,12 @@ export function pushToastInfo(
);
}
+/**
+ * We are rendering a toast. A toast is only rendering a string and no html at all.
+ * We have to strip the html tags from the strings we are given.
+ */
+const getStrippedI18n = window.i18n.stripped;
+
export function pushToastSuccess(id: string, title: string, description?: string) {
toast.success(
,
@@ -44,84 +50,72 @@ export function pushToastSuccess(id: string, title: string, description?: string
export function pushLoadAttachmentFailure(message?: string) {
if (message) {
- pushToastError('unableToLoadAttachment', `${window.i18n('attachmentsErrorLoad')} ${message}`);
+ pushToastError(
+ 'unableToLoadAttachment',
+ `${getStrippedI18n('attachmentsErrorLoad')} ${message}`
+ );
} else {
- pushToastError('unableToLoadAttachment', window.i18n('attachmentsErrorLoad'));
+ pushToastError('unableToLoadAttachment', getStrippedI18n('attachmentsErrorLoad'));
}
}
-export function pushFileSizeError(limit: number, units: string) {
- pushToastError(
- 'fileSizeWarning',
- window.i18n('attachmentsErrorSize'),
- `Max size: ${limit} ${units}`
- );
-}
-
-export function pushFileSizeErrorAsByte(bytesCount: number) {
- const units = ['kB', 'MB', 'GB'];
- let u = -1;
- let limit = bytesCount;
- do {
- limit /= 1000;
- u += 1;
- } while (limit >= 1000 && u < units.length - 1);
- pushFileSizeError(limit, units[u]);
+export function pushFileSizeErrorAsByte() {
+ pushToastError('fileSizeWarning', getStrippedI18n('attachmentsErrorSize'));
}
export function pushMultipleNonImageError() {
- pushToastError('cannotMixImageAndNonImageAttachments', window.i18n('attachmentsErrorTypes'));
+ pushToastError('attachmentsErrorTypes', getStrippedI18n('attachmentsErrorTypes'));
}
export function pushCannotMixError() {
- pushToastError('oneNonImageAtATimeToast', window.i18n('attachmentsErrorTypes'));
+ pushToastError('attachmentsErrorTypes', getStrippedI18n('attachmentsErrorTypes'));
}
export function pushMaximumAttachmentsError() {
- pushToastError('maximumAttachments', window.i18n('attachmentsErrorNumber'));
+ pushToastError('attachmentsErrorNumber', getStrippedI18n('attachmentsErrorNumber'));
}
export function pushCopiedToClipBoard() {
- pushToastInfo('copiedToClipboard', window.i18n('copied'));
+ pushToastInfo('copiedToClipboard', getStrippedI18n('copied'));
}
export function pushRestartNeeded() {
- pushToastInfo('restartNeeded', window.i18n('settingsRestartDescription'));
+ pushToastInfo('restartNeeded', getStrippedI18n('settingsRestartDescription'));
}
export function pushAlreadyMemberOpenGroup() {
- pushToastInfo('publicChatExists', window.i18n('communityJoinedAlready'));
+ pushToastInfo('publicChatExists', getStrippedI18n('communityJoinedAlready'));
}
export function pushUserBanSuccess() {
- pushToastSuccess('userBanned', window.i18n('banUserBanned'));
+ pushToastSuccess('userBanned', getStrippedI18n('banUserBanned'));
}
export function pushUserBanFailure() {
- pushToastError('userBanFailed', window.i18n('banErrorFailed'));
+ pushToastError('userBanFailed', getStrippedI18n('banErrorFailed'));
}
export function pushUserUnbanSuccess() {
- pushToastSuccess('userUnbanned', window.i18n('banUnbanUserUnbanned'));
+ pushToastSuccess('userUnbanned', getStrippedI18n('banUnbanUserUnbanned'));
}
export function pushUserUnbanFailure() {
- pushToastError('userUnbanFailed', window.i18n('banUnbanErrorFailed'));
+ pushToastError('userUnbanFailed', getStrippedI18n('banUnbanErrorFailed'));
}
export function pushMessageDeleteForbidden() {
pushToastError(
'messageDeletionForbidden',
- window.i18n('deleteafterMessageDeletionStandardisationmessageDeletionForbidden')
+ getStrippedI18n('deleteafterMessageDeletionStandardisationmessageDeletionForbidden')
);
}
export function pushUnableToCall() {
- pushToastError('unableToCall', window.i18n('callsCannotStart'), window.i18n('callsCannotStart'));
+ pushToastError('unableToCall', getStrippedI18n('callsCannotStart'));
}
-export function pushedMissedCall(conversationName: string) {
- pushToastInfo('missedCall', window.i18n('callsMissedCallFrom', { name: conversationName }));
+export function pushedMissedCall(userName: string) {
+ pushToastInfo('missedCall', getStrippedI18n('callsMissedCallFrom', { name: userName }));
}
const openPermissionsSettings = () => {
@@ -133,8 +127,8 @@ export function pushedMissedCallCauseOfPermission(conversationName: string) {
const id = 'missedCallPermission';
toast.info(
,
@@ -145,8 +139,8 @@ export function pushedMissedCallCauseOfPermission(conversationName: string) {
export function pushVideoCallPermissionNeeded() {
pushToastInfo(
'videoCallPermissionNeeded',
- window.i18n('callsPermissionsRequired'),
- window.i18n('callsPermissionsRequiredDescription'),
+ getStrippedI18n('callsPermissionsRequired'),
+ getStrippedI18n('callsPermissionsRequiredDescription'),
openPermissionsSettings
);
}
@@ -154,83 +148,123 @@ export function pushVideoCallPermissionNeeded() {
export function pushAudioPermissionNeeded() {
pushToastInfo(
'audioPermissionNeeded',
- window.i18n('permissionsMicrophoneAccessRequiredDesktop'),
+ getStrippedI18n('permissionsMicrophoneAccessRequiredDesktop'),
undefined,
openPermissionsSettings
);
}
export function pushOriginalNotFound() {
- pushToastError('originalMessageNotFound', window.i18n('messageErrorOriginal'));
+ pushToastError('messageErrorOriginal', getStrippedI18n('messageErrorOriginal'));
}
export function pushTooManyMembers() {
- pushToastError('tooManyMembers', window.i18n('groupAddMemberMaximum'));
+ pushToastError('groupAddMemberMaximum', getStrippedI18n('groupAddMemberMaximum'));
}
export function pushMessageRequestPending() {
- pushToastInfo('messageRequestPending', window.i18n('messageRequestPending'));
+ pushToastInfo('messageRequestPending', getStrippedI18n('messageRequestPending'));
}
export function pushUnblockToSend() {
- pushToastInfo('unblockToSend', window.i18n('blockBlockedDescription'));
+ pushToastInfo('unblockToSend', getStrippedI18n('blockBlockedDescription'));
}
export function pushYouLeftTheGroup() {
- pushToastError('youLeftTheGroup', window.i18n('groupMemberYouLeft'));
+ pushToastError('youLeftTheGroup', getStrippedI18n('groupMemberYouLeft'));
}
-export function someDeletionsFailed() {
- pushToastWarning('deletionError', 'Deletion error');
+export function someDeletionsFailed(count: number) {
+ pushToastWarning('deletionError', getStrippedI18n('deleteMessagesFailed', { count }));
}
export function pushDeleted() {
- pushToastSuccess('deleted', window.i18n('deleteMessagesDeleted'), undefined);
+ pushToastSuccess('deleted', getStrippedI18n('deleteMessagesDeleted'), undefined);
}
export function pushCannotRemoveCreatorFromGroup() {
- pushToastWarning('adminCannotBeRemoved', window.i18n('adminCannotBeRemoved'));
+ pushToastWarning('adminCannotBeRemoved', getStrippedI18n('adminCannotBeRemoved'));
}
export function pushFailedToAddAsModerator() {
- pushToastWarning('adminPromotionFailed', window.i18n('adminPromotionFailed'));
-}
-
-export function pushFailedToRemoveFromModerator(name: string) {
- pushToastWarning(
- 'adminRemoveFailed',
- window.i18n('adminRemoveFailed', {
- name,
- })
- );
+ pushToastWarning('adminPromotionFailed', getStrippedI18n('adminPromotionFailed'));
+}
+
+export function pushFailedToRemoveFromModerator(names: Array) {
+ let localizedString: string = '';
+ switch (names.length) {
+ case 0:
+ throw new Error('pushFailedToRemoveFromModerator invalid case error');
+ case 1:
+ localizedString = getStrippedI18n('adminRemoveFailed', {
+ name: names[0],
+ });
+ break;
+ case 2:
+ localizedString = getStrippedI18n('adminRemoveFailedOther', {
+ name: names[0],
+ other_name: names[1],
+ });
+ break;
+ default:
+ localizedString = getStrippedI18n('adminRemoveFailedMultiple', {
+ name: names[0],
+ count: names.length - 1,
+ });
+ break;
+ }
+ pushToastWarning('adminRemoveFailed', localizedString);
}
export function pushUserAddedToModerators(name: string) {
- pushToastSuccess('adminPromotedToAdmin', window.i18n('adminPromotedToAdmin', { name }));
-}
+ pushToastSuccess('adminPromotedToAdmin', getStrippedI18n('adminPromotedToAdmin', { name }));
+}
+
+export function pushUserRemovedFromModerators(names: Array) {
+ let localizedString: string = '';
+ switch (names.length) {
+ case 0:
+ throw new Error('pushUserRemovedFromModerators invalid case error');
+ case 1:
+ localizedString = getStrippedI18n('adminRemovedUser', {
+ name: names[0],
+ });
+ break;
+ case 2:
+ localizedString = getStrippedI18n('adminRemovedUserOther', {
+ name: names[0],
+ other_name: names[1],
+ });
+ break;
+ default:
+ localizedString = getStrippedI18n('adminRemovedUserMultiple', {
+ name: names[0],
+ count: names.length - 1,
+ });
+ break;
+ }
-export function pushUserRemovedFromModerators(name: string) {
- pushToastSuccess('adminRemovedUser', window.i18n('adminRemovedUser', { name }));
+ pushToastSuccess('adminRemovedUser', localizedString);
}
export function pushInvalidPubKey() {
- pushToastSuccess('invalidPubKey', window.i18n('accountIdErrorInvalid'));
+ pushToastSuccess('accountIdErrorInvalid', getStrippedI18n('accountIdErrorInvalid'));
}
export function pushNoCameraFound() {
- pushToastWarning('noCameraFound', window.i18n('cameraErrorNotFound'));
+ pushToastWarning('noCameraFound', getStrippedI18n('cameraErrorNotFound'));
}
export function pushNoAudioInputFound() {
- pushToastWarning('noAudioInputFound', window.i18n('audioNoInput'));
+ pushToastWarning('noAudioInputFound', getStrippedI18n('audioNoInput'));
}
export function pushNoAudioOutputFound() {
- pushToastWarning('noAudioOutputFound', window.i18n('audioNoOutput'));
+ pushToastWarning('noAudioOutputFound', getStrippedI18n('audioNoOutput'));
}
export function pushNoMediaUntilApproved() {
- pushToastError('noMediaUntilApproved', window.i18n('messageRequestPendingDescription'));
+ pushToastError('noMediaUntilApproved', getStrippedI18n('messageRequestPendingDescription'));
}
export function pushRateLimitHitReactions() {
diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts
index 5473c6e55..403541d6b 100644
--- a/ts/state/selectors/conversations.ts
+++ b/ts/state/selectors/conversations.ts
@@ -26,7 +26,6 @@ import { hasValidIncomingRequestValues } from '../../models/conversation';
import { isOpenOrClosedGroup } from '../../models/conversationAttributes';
import { getConversationController } from '../../session/conversations';
import { UserUtils } from '../../session/utils';
-import { LocalizerType } from '../../types/Util';
import { BlockedNumberController } from '../../util';
import { Storage } from '../../util/storage';
import { getIntl } from './user';
@@ -220,23 +219,20 @@ export const getSortedMessagesTypesOfSelectedConversation = createSelector(
}
);
-function getConversationTitle(
- conversation: ReduxConversationType,
- testingi18n?: LocalizerType
-): string {
+function getConversationTitle(conversation: ReduxConversationType): string {
if (conversation.displayNameInProfile) {
return conversation.displayNameInProfile;
}
if (isOpenOrClosedGroup(conversation.type)) {
- return (testingi18n || window.i18n)('unknown');
+ return window.i18n('unknown');
}
return conversation.id;
}
const collator = new Intl.Collator();
-export const _getConversationComparator = (testingi18n?: LocalizerType) => {
+export const _getConversationComparator = () => {
return (left: ReduxConversationType, right: ReduxConversationType): number => {
// Pin is the first criteria to check
const leftPriority = left.priority || 0;
@@ -259,8 +255,8 @@ export const _getConversationComparator = (testingi18n?: LocalizerType) => {
if (leftActiveAt && rightActiveAt && leftActiveAt !== rightActiveAt) {
return rightActiveAt - leftActiveAt;
}
- const leftTitle = getConversationTitle(left, testingi18n).toLowerCase();
- const rightTitle = getConversationTitle(right, testingi18n).toLowerCase();
+ const leftTitle = getConversationTitle(left).toLowerCase();
+ const rightTitle = getConversationTitle(right).toLowerCase();
return collator.compare(leftTitle, rightTitle);
};
diff --git a/ts/test/session/unit/selectors/conversations_test.ts b/ts/test/session/unit/selectors/conversations_test.ts
index 43562a743..8664877b7 100644
--- a/ts/test/session/unit/selectors/conversations_test.ts
+++ b/ts/test/session/unit/selectors/conversations_test.ts
@@ -1,22 +1,22 @@
import { assert } from 'chai';
+import Sinon from 'sinon';
+import { CONVERSATION_PRIORITIES, ConversationTypeEnum } from '../../../../models/types';
import { ConversationLookupType } from '../../../../state/ducks/conversations';
import {
_getConversationComparator,
_getSortedConversations,
} from '../../../../state/selectors/conversations';
-import { ConversationTypeEnum, CONVERSATION_PRIORITIES } from '../../../../models/types';
-import type {
- GetMessageArgs,
- LocalizerDictionary,
- LocalizerToken,
-} from '../../../../types/Localizer';
-
-const i18n = (
- ...[token]: GetMessageArgs
-) => token as any as R;
+import { TestUtils } from '../../../test-utils';
describe('state/selectors/conversations', () => {
+ beforeEach(() => {
+ TestUtils.stubWindowLog();
+ TestUtils.stubI18n();
+ });
+ afterEach(() => {
+ Sinon.restore();
+ });
describe('#getSortedConversationsList', () => {
it('sorts conversations based on timestamp then by intl-friendly title', () => {
const data: ConversationLookupType = {
@@ -138,7 +138,7 @@ describe('state/selectors/conversations', () => {
priority: CONVERSATION_PRIORITIES.default,
},
};
- const comparator = _getConversationComparator(i18n);
+ const comparator = _getConversationComparator();
const conversations = _getSortedConversations(data, comparator);
assert.strictEqual(conversations[0].displayNameInProfile, 'First!');
@@ -277,7 +277,7 @@ describe('state/selectors/conversations', () => {
isPublic: false,
},
};
- const comparator = _getConversationComparator(i18n);
+ const comparator = _getConversationComparator();
const conversations = _getSortedConversations(data, comparator);
assert.strictEqual(conversations[0].displayNameInProfile, 'Á');
diff --git a/ts/util/i18n.ts b/ts/util/i18n.ts
index 82e6292c5..fd5880a7d 100644
--- a/ts/util/i18n.ts
+++ b/ts/util/i18n.ts
@@ -13,6 +13,9 @@ import {
} from 'date-fns';
import timeLocales from 'date-fns/locale';
import { isUndefined } from 'lodash';
+import { GetNetworkTime } from '../session/apis/snode_api/getNetworkTime';
+import { DURATION_SECONDS, LOCALE_DEFAULTS } from '../session/constants';
+import { updateLocale } from '../state/ducks/dictionary';
import {
DictionaryWithoutPluralStrings,
GetMessageArgs,
@@ -21,10 +24,6 @@ import {
PluralKey,
PluralString,
} from '../types/Localizer';
-import { DURATION_SECONDS, LOCALE_DEFAULTS } from '../session/constants';
-import { updateLocale } from '../state/ducks/dictionary';
-import { GetNetworkTime } from '../session/apis/snode_api/getNetworkTime';
-import { Dictionary } from '../localization/locales';
export function loadDictionary(locale: Locale) {
return import(`../../_locales/${locale}/messages.json`) as Promise;
@@ -232,7 +231,7 @@ export const setupi18n = (locale: Locale, dictionary: LocalizerDictionary) => {
return token as R;
}
- localizedString = pluralString.replaceAll('#', num) as R;
+ localizedString = pluralString.replaceAll('#', `${num}`) as R;
}
}