diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 04d0644610..2b84c570b8 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -155,7 +155,6 @@ window.SignalContext = { _stopTrackingICUStrings: () => i18n.stopTrackingUsage(), }; -window.i18n = i18n; window.ConversationController = window.ConversationController || {}; window.ConversationController.isSignalConversationId = () => false; window.ConversationController.onConvoMessageMount = noop; diff --git a/test/setup-test-node.js b/test/setup-test-node.js index 3baf460c96..d955582c9e 100644 --- a/test/setup-test-node.js +++ b/test/setup-test-node.js @@ -18,6 +18,7 @@ global.window = { Date, performance, SignalContext: { + i18n: key => `i18n(${key})`, getPath: () => '/tmp', getVersion: () => package.version, config: { @@ -35,7 +36,6 @@ global.window = { getPreferredSystemLocales: () => ['en'], getLocaleOverride: () => null, }, - i18n: key => `i18n(${key})`, }; // For ducks/network.getEmptyState() diff --git a/ts/background.ts b/ts/background.ts index 1fa54251ea..f704032b83 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -277,6 +277,7 @@ import { itemStorage } from './textsecure/Storage.js'; const { isNumber, throttle } = lodash; const log = createLogger('background'); +const { i18n } = window.SignalContext; export function isOverHourIntoPast(timestamp: number): boolean { return isNumber(timestamp) && isOlderThan(timestamp, HOUR); @@ -313,7 +314,7 @@ export async function startApp(): Promise { StartupQueue.initialize(); notificationService.initialize({ - i18n: window.i18n, + i18n, storage: itemStorage, }); @@ -477,7 +478,7 @@ export async function startApp(): Promise { const cancelInitializationMessage = setAppLoadingScreenMessage( undefined, - window.i18n + i18n ); const version = await DataReader.getItemById('version'); @@ -494,10 +495,10 @@ export async function startApp(): Promise { dialogName: 'deleteOldIndexedDBData', noMouseClose: true, onTopOfEverything: true, - cancelText: window.i18n('icu:quit'), + cancelText: i18n('icu:quit'), confirmStyle: 'negative', - title: window.i18n('icu:deleteOldIndexedDBData'), - okText: window.i18n('icu:deleteOldData'), + title: i18n('icu:deleteOldIndexedDBData'), + okText: i18n('icu:deleteOldData'), reject: () => reject(), resolve: () => resolve(), }); @@ -1012,10 +1013,7 @@ export async function startApp(): Promise { } } - setAppLoadingScreenMessage( - window.i18n('icu:optimizingApplication'), - window.i18n - ); + setAppLoadingScreenMessage(i18n('icu:optimizingApplication'), i18n); if (newVersion || itemStorage.get('needOrphanedAttachmentCheck')) { await itemStorage.remove('needOrphanedAttachmentCheck'); @@ -1031,7 +1029,7 @@ export async function startApp(): Promise { await Stickers.encryptLegacyStickers(); } - setAppLoadingScreenMessage(window.i18n('icu:loading'), window.i18n); + setAppLoadingScreenMessage(i18n('icu:loading'), i18n); let isMigrationWithIndexComplete = false; let isIdleTaskProcessing = false; diff --git a/ts/components/DonationsErrorBoundary.tsx b/ts/components/DonationsErrorBoundary.tsx index 5bfa3ecbb0..7a9791f95f 100644 --- a/ts/components/DonationsErrorBoundary.tsx +++ b/ts/components/DonationsErrorBoundary.tsx @@ -58,7 +58,7 @@ export function DonationsErrorBoundary( if (window.reduxActions) { window.reduxActions.globalModals.showDebugLogErrorModal({ - description: window.i18n( + description: window.SignalContext.i18n( 'icu:DonationsErrorBoundary__DonationUnexpectedError' ), }); diff --git a/ts/groups/joinViaLink.ts b/ts/groups/joinViaLink.ts index 1015be1d14..c55dbf8056 100644 --- a/ts/groups/joinViaLink.ts +++ b/ts/groups/joinViaLink.ts @@ -39,6 +39,7 @@ import { missingCaseError } from '../util/missingCaseError.js'; import { itemStorage } from '../textsecure/Storage.js'; const log = createLogger('joinViaLink'); +const { i18n } = window.SignalContext; export async function joinViaLink(value: string): Promise { let inviteLinkPassword: string; @@ -51,13 +52,13 @@ export async function joinViaLink(value: string): Promise { if (error instanceof Error && error.name === LINK_VERSION_ERROR) { window.reduxActions.globalModals.showErrorModal({ - description: window.i18n('icu:GroupV2--join--unknown-link-version'), - title: window.i18n('icu:GroupV2--join--unknown-link-version--title'), + description: i18n('icu:GroupV2--join--unknown-link-version'), + title: i18n('icu:GroupV2--join--unknown-link-version--title'), }); } else { window.reduxActions.globalModals.showErrorModal({ - description: window.i18n('icu:GroupV2--join--invalid-link'), - title: window.i18n('icu:GroupV2--join--invalid-link--title'), + description: i18n('icu:GroupV2--join--invalid-link'), + title: i18n('icu:GroupV2--join--invalid-link--title'), }); } return; @@ -105,18 +106,18 @@ export async function joinViaLink(value: string): Promise { error.responseHeaders['x-signal-forbidden-reason'] ) { window.reduxActions.globalModals.showErrorModal({ - description: window.i18n('icu:GroupV2--join--link-forbidden'), - title: window.i18n('icu:GroupV2--join--link-forbidden--title'), + description: i18n('icu:GroupV2--join--link-forbidden'), + title: i18n('icu:GroupV2--join--link-forbidden--title'), }); } else if (error instanceof HTTPError && error.code === 403) { window.reduxActions.globalModals.showErrorModal({ - description: window.i18n('icu:GroupV2--join--link-revoked'), - title: window.i18n('icu:GroupV2--join--link-revoked--title'), + description: i18n('icu:GroupV2--join--link-revoked'), + title: i18n('icu:GroupV2--join--link-revoked--title'), }); } else { window.reduxActions.globalModals.showErrorModal({ - description: window.i18n('icu:GroupV2--join--general-join-failure'), - title: window.i18n('icu:GroupV2--join--general-join-failure--title'), + description: i18n('icu:GroupV2--join--general-join-failure'), + title: i18n('icu:GroupV2--join--general-join-failure--title'), }); } return; @@ -127,8 +128,8 @@ export async function joinViaLink(value: string): Promise { `${logId}: addFromInviteLink value of ${result.addFromInviteLink} is invalid` ); window.reduxActions.globalModals.showErrorModal({ - description: window.i18n('icu:GroupV2--join--link-revoked'), - title: window.i18n('icu:GroupV2--join--link-revoked--title'), + description: i18n('icu:GroupV2--join--link-revoked'), + title: i18n('icu:GroupV2--join--link-revoked--title'), }); return; } @@ -147,7 +148,7 @@ export async function joinViaLink(value: string): Promise { Proto.AccessControl.AccessRequired.ADMINISTRATOR; const title = decryptGroupTitle(dropNull(result.title), secretParams) || - window.i18n('icu:unknownGroup'); + i18n('icu:unknownGroup'); const groupDescription = decryptGroupDescription( dropNull(result.descriptionBytes), secretParams diff --git a/ts/mediaEditor/util/moreStyles.ts b/ts/mediaEditor/util/moreStyles.ts index 78183364e3..d1309cc0e8 100644 --- a/ts/mediaEditor/util/moreStyles.ts +++ b/ts/mediaEditor/util/moreStyles.ts @@ -9,7 +9,7 @@ function render( ctx.save(); ctx.font = '11px Inter'; - const text = window.i18n('icu:MediaEditor__clock-more-styles'); + const text = window.SignalContext.i18n('icu:MediaEditor__clock-more-styles'); const textMetrics = ctx.measureText(text); const boxHeight = textMetrics.fontBoundingBoxAscent * 2; diff --git a/ts/messages/maybeNotify.ts b/ts/messages/maybeNotify.ts index 5e16e73981..7bfc42ec0b 100644 --- a/ts/messages/maybeNotify.ts +++ b/ts/messages/maybeNotify.ts @@ -39,6 +39,8 @@ export async function maybeNotify(args: MaybeNotifyArgs): Promise { return; } + const { i18n } = window.SignalContext; + const { conversation, reaction } = args; let warrantsNotification: boolean; @@ -79,12 +81,10 @@ export async function maybeNotify(args: MaybeNotifyArgs): Promise { const sender = reaction ? window.ConversationController.get(reaction.fromId) : getAuthor(args.message); - const senderName = sender - ? sender.getTitle() - : window.i18n('icu:unknownContact'); + const senderName = sender ? sender.getTitle() : i18n('icu:unknownContact'); const senderTitle = isMessageInDirectConversation ? senderName - : window.i18n('icu:notificationSenderInGroup', { + : i18n('icu:notificationSenderInGroup', { sender: senderName, group: conversation.getTitle(), }); diff --git a/ts/quill/mentions/blot.tsx b/ts/quill/mentions/blot.tsx index 74953111b8..54f2c90ff7 100644 --- a/ts/quill/mentions/blot.tsx +++ b/ts/quill/mentions/blot.tsx @@ -11,6 +11,8 @@ import type { MentionBlotValue } from '../util.js'; import { FunEmojiLocalizationProvider } from '../../components/fun/FunEmojiLocalizationProvider.js'; import { AxoProvider } from '../../axo/AxoProvider.js'; +const { i18n } = window.SignalContext; + export class MentionBlot extends EmbedBlot { static override blotName = 'mention'; @@ -49,8 +51,8 @@ export class MentionBlot extends EmbedBlot { createRoot(mentionSpan).render( - - + + @ diff --git a/ts/services/LinkPreview.ts b/ts/services/LinkPreview.ts index 46228fd4bb..44ceec6b37 100644 --- a/ts/services/LinkPreview.ts +++ b/ts/services/LinkPreview.ts @@ -52,6 +52,7 @@ import { itemStorage } from '../textsecure/Storage.js'; const { debounce, omit } = lodash; const log = createLogger('LinkPreview'); +const { i18n } = window.SignalContext; const LINK_PREVIEW_TIMEOUT = 60 * SECOND; @@ -544,8 +545,8 @@ async function getGroupPreview( const title = decryptGroupTitle(dropNull(result.title), secretParams) || - window.i18n('icu:unknownGroup'); - const description = window.i18n('icu:GroupV2--join--group-metadata--full', { + i18n('icu:unknownGroup'); + const description = i18n('icu:GroupV2--join--group-metadata--full', { memberCount: result?.memberCount ?? 0, }); let image: undefined | LinkPreviewImage; @@ -603,9 +604,9 @@ async function getCallLinkPreview( url, title: callLinkState.name === '' - ? window.i18n('icu:calling__call-link-default-title') + ? i18n('icu:calling__call-link-default-title') : callLinkState.name, - description: window.i18n('icu:message--call-link-description'), + description: i18n('icu:message--call-link-description'), image: undefined, date: null, }; diff --git a/ts/services/calling.ts b/ts/services/calling.ts index fe99597717..9bb6777322 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -174,6 +174,8 @@ import { sleep } from '../util/sleep.js'; import { signalProtocolStore } from '../SignalProtocolStore.js'; import { itemStorage } from '../textsecure/Storage.js'; +const { i18n } = window.SignalContext; + const { uniqBy, noop, compact } = lodash; const log = createLogger('calling'); @@ -2521,11 +2523,11 @@ export class CallingClass { conversationId, iconPath: absolutePath, iconUrl: url, - message: window.i18n('icu:calling__presenting--notification-body'), + message: i18n('icu:calling__presenting--notification-body'), type: NotificationType.IsPresenting, sentAt: 0, silent: true, - title: window.i18n('icu:calling__presenting--notification-title'), + title: i18n('icu:calling__presenting--notification-title'), }); } else { ipcRenderer.send( @@ -2592,13 +2594,13 @@ export class CallingClass { conversationId, iconPath: absolutePath, iconUrl: url, - message: window.i18n( + message: i18n( 'icu:calling__presenting--reconnecting--notification-body' ), type: NotificationType.IsPresenting, sentAt: 0, silent: true, - title: window.i18n( + title: i18n( 'icu:calling__presenting--reconnecting--notification-title' ), }); @@ -3922,7 +3924,7 @@ export class CallingClass { } case NotificationSetting.NoNameOrMessage: { notificationTitle = FALLBACK_NOTIFICATION_TITLE; - notificationMessage = window.i18n( + notificationMessage = i18n( 'icu:calling__call-notification__started-by-someone' ); break; @@ -3932,10 +3934,10 @@ export class CallingClass { notificationTitle = conversation?.getTitle() || FALLBACK_NOTIFICATION_TITLE; notificationMessage = creatorConversation - ? window.i18n('icu:calling__call-notification__started', { + ? i18n('icu:calling__call-notification__started', { name: creatorConversation.getTitle(), }) - : window.i18n('icu:calling__call-notification__started-by-someone'); + : i18n('icu:calling__call-notification__started-by-someone'); const iconData = await conversation.getAvatarOrIdenticon(); url = iconData.url; absolutePath = iconData.absolutePath; @@ -4009,8 +4011,8 @@ export class CallingClass { iconPath: absolutePath, iconUrl: url, message: isVideoCall - ? window.i18n('icu:incomingVideoCall') - : window.i18n('icu:incomingAudioCall'), + ? i18n('icu:incomingVideoCall') + : i18n('icu:incomingAudioCall'), sentAt: 0, // The ringtone plays so we don't need sound for the notification silent: true, diff --git a/ts/services/notifications.ts b/ts/services/notifications.ts index 724eb01b09..7f79d8e6ef 100644 --- a/ts/services/notifications.ts +++ b/ts/services/notifications.ts @@ -133,9 +133,10 @@ class NotificationService extends EventEmitter { } log.error( - 'NotificationService not initialized. Falling back to window.i18n, but you should fix this' + 'NotificationService not initialized. ' + + 'Falling back to window.SignalContext.i18n, but you should fix this' ); - return window.i18n; + return window.SignalContext.i18n; } /** diff --git a/ts/services/storageRecordOps.ts b/ts/services/storageRecordOps.ts index 6c7408a143..644fb4a146 100644 --- a/ts/services/storageRecordOps.ts +++ b/ts/services/storageRecordOps.ts @@ -2797,7 +2797,7 @@ export function prepareForEnabledNotificationProfileSync(): { toRemove.push(local.profile); toAdd.push({ ...local.profile, - name: window.i18n('icu:NotificationProfile--copy-label', { + name: window.SignalContext.i18n('icu:NotificationProfile--copy-label', { profileName: local.profile.name, }), }); diff --git a/ts/shims/renderClearingDataView.tsx b/ts/shims/renderClearingDataView.tsx index 5f2469cd74..bbc43e0928 100644 --- a/ts/shims/renderClearingDataView.tsx +++ b/ts/shims/renderClearingDataView.tsx @@ -15,9 +15,12 @@ export function renderClearingDataView(): void { strictAssert(appContainer != null, 'No #app-container'); createRoot(appContainer).render( - + - + diff --git a/ts/state/getInitialState.ts b/ts/state/getInitialState.ts index 7f6c21ec8f..9338473376 100644 --- a/ts/state/getInitialState.ts +++ b/ts/state/getInitialState.ts @@ -222,11 +222,11 @@ export function generateUserState({ return { ...userEmptyState(), attachmentsPath: ATTACHMENTS_PATH, - i18n: window.i18n, + i18n: window.SignalContext.i18n, interactionMode: getInteractionMode(), isMainWindowFullScreen: mainWindowStats.isFullScreen, isMainWindowMaximized: mainWindowStats.isMaximized, - localeMessages: window.i18n.getLocaleMessages(), + localeMessages: window.SignalContext.i18n.getLocaleMessages(), menuOptions, osName, ourAci, diff --git a/ts/state/roots/createApp.tsx b/ts/state/roots/createApp.tsx index 7957b83b60..d690186c0e 100644 --- a/ts/state/roots/createApp.tsx +++ b/ts/state/roots/createApp.tsx @@ -12,7 +12,7 @@ import { SmartVoiceNotesPlaybackProvider } from '../smart/VoiceNotesPlaybackProv import { AxoProvider } from '../../axo/AxoProvider.js'; export const createApp = (store: Store): ReactElement => ( - + diff --git a/ts/state/roots/createGroupV2JoinModal.tsx b/ts/state/roots/createGroupV2JoinModal.tsx index a9fb65e299..97cc507f34 100644 --- a/ts/state/roots/createGroupV2JoinModal.tsx +++ b/ts/state/roots/createGroupV2JoinModal.tsx @@ -21,7 +21,7 @@ export const createGroupV2JoinModal = ( return ( - + diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index eaae9af813..a376ec3152 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -102,7 +102,7 @@ export const getPlaceholderContact = (): ConversationType => { badges: [], id: PLACEHOLDER_CONTACT_ID, type: 'direct', - title: window.i18n('icu:unknownContact'), + title: window.SignalContext.i18n('icu:unknownContact'), isMe: false, sharedGroupNames: [], }; diff --git a/ts/state/selectors/message.ts b/ts/state/selectors/message.ts index 8f72460f0e..093c0cbdb1 100644 --- a/ts/state/selectors/message.ts +++ b/ts/state/selectors/message.ts @@ -613,7 +613,10 @@ const getPropsForStoryReplyContext = ( ? processQuoteAttachment(storyReplyContext.attachment) : undefined, storyId: storyReplyContext.messageId, - text: getStoryReplyText(window.i18n, storyReplyContext.attachment), + text: getStoryReplyText( + window.SignalContext.i18n, + storyReplyContext.attachment + ), }; }; diff --git a/ts/state/smart/CallManager.tsx b/ts/state/smart/CallManager.tsx index 5f2d019bd8..44e1487a63 100644 --- a/ts/state/smart/CallManager.tsx +++ b/ts/state/smart/CallManager.tsx @@ -99,7 +99,7 @@ const mapStateToActiveCallProp = ( return undefined; } - conversation = callLinkToConversation(callLink, window.i18n); + conversation = callLinkToConversation(callLink, window.SignalContext.i18n); } else { conversation = conversationSelector(activeCallState.conversationId); } diff --git a/ts/test-node/util/messageFailures.ts b/ts/test-node/util/messageFailures.ts index 2626346a5f..39a63ae018 100644 --- a/ts/test-node/util/messageFailures.ts +++ b/ts/test-node/util/messageFailures.ts @@ -28,6 +28,7 @@ import type { MessageModel } from '../../models/messages.js'; const { mapValues, pick } = lodash; const log = createLogger('messageFailures'); +const { i18n } = window.SignalContext; export async function saveErrorsOnMessage( message: MessageModel, @@ -140,10 +141,10 @@ export function notifyStorySendFailed(message: MessageModel): void { conversationId, storyId: id, messageId: id, - senderTitle: conversation?.getTitle() ?? window.i18n('icu:Stories__mine'), + senderTitle: conversation?.getTitle() ?? i18n('icu:Stories__mine'), message: hasSuccessfulDelivery(message.attributes) - ? window.i18n('icu:Stories__failed-send--partial') - : window.i18n('icu:Stories__failed-send--full'), + ? i18n('icu:Stories__failed-send--partial') + : i18n('icu:Stories__failed-send--full'), isExpiringMessage: false, sentAt: timestamp, type: NotificationType.Message, diff --git a/ts/util/createIPCEvents.ts b/ts/util/createIPCEvents.ts index a31461fd41..5432223971 100644 --- a/ts/util/createIPCEvents.ts +++ b/ts/util/createIPCEvents.ts @@ -37,6 +37,7 @@ import OS from './os/osPreload.js'; const { noop } = lodash; const log = createLogger('createIPCEvents'); +const { i18n } = window.SignalContext; export type IPCEventsValuesType = { // IPC-mediated @@ -276,14 +277,14 @@ export function createIPCEvents( showConfirmationDialog({ dialogName: 'closeConfirmation', onTopOfEverything: true, - cancelText: window.i18n( + cancelText: i18n( 'icu:ConfirmationDialog__Title--close-requested-not-now' ), confirmStyle: 'negative', - title: window.i18n( + title: i18n( 'icu:ConfirmationDialog__Title--in-call-close-requested' ), - okText: window.i18n('icu:close'), + okText: i18n('icu:close'), reject: () => reject(), resolve: () => resolve(), }); @@ -402,8 +403,8 @@ export function createIPCEvents( Errors.toLogFormat(error) ); window.reduxActions.globalModals.showErrorModal({ - title: window.i18n('icu:GroupV2--join--general-join-failure--title'), - description: window.i18n('icu:GroupV2--join--general-join-failure'), + title: i18n('icu:GroupV2--join--general-join-failure--title'), + description: i18n('icu:GroupV2--join--general-join-failure'), }); } }, @@ -448,7 +449,7 @@ export function createIPCEvents( function showUnknownSgnlLinkModal(): void { window.reduxActions.globalModals.showErrorModal({ - description: window.i18n('icu:unknown-sgnl-link'), + description: i18n('icu:unknown-sgnl-link'), }); } diff --git a/ts/util/downloadOnboardingStory.ts b/ts/util/downloadOnboardingStory.ts index 01894330f9..0abce15f0f 100644 --- a/ts/util/downloadOnboardingStory.ts +++ b/ts/util/downloadOnboardingStory.ts @@ -46,7 +46,7 @@ export async function downloadOnboardingStory(): Promise { return; } - const userLocale = window.i18n.getLocale(); + const userLocale = window.SignalContext.i18n.getLocale(); const manifest = await getOnboardingStoryManifest(); diff --git a/ts/util/filterCallLinks.ts b/ts/util/filterCallLinks.ts index 429cc8ec6f..3973af08b7 100644 --- a/ts/util/filterCallLinks.ts +++ b/ts/util/filterCallLinks.ts @@ -25,7 +25,7 @@ const FUSE_OPTIONS: Fuse.IFuseOptions = { item.name === '' ) { return removeDiacritics( - window.i18n('icu:calling__call-link-default-title') + window.SignalContext.i18n('icu:calling__call-link-default-title') ); } diff --git a/ts/util/findAndFormatContact.ts b/ts/util/findAndFormatContact.ts index 4d46b7d571..2ec3c352e2 100644 --- a/ts/util/findAndFormatContact.ts +++ b/ts/util/findAndFormatContact.ts @@ -12,7 +12,7 @@ const PLACEHOLDER_CONTACT: ConversationType = { id: PLACEHOLDER_CONTACT_ID, isMe: false, sharedGroupNames: [], - title: window.i18n('icu:unknownContact'), + title: window.SignalContext.i18n('icu:unknownContact'), type: 'direct', }; diff --git a/ts/util/getAboutText.ts b/ts/util/getAboutText.ts index ec0573fb63..f1d5600867 100644 --- a/ts/util/getAboutText.ts +++ b/ts/util/getAboutText.ts @@ -18,8 +18,11 @@ export function getAboutText( return text; } - return window.i18n('icu:message--getNotificationText--text-with-emoji', { - text, - emoji, - }); + return window.SignalContext.i18n( + 'icu:message--getNotificationText--text-with-emoji', + { + text, + emoji, + } + ); } diff --git a/ts/util/getConversation.ts b/ts/util/getConversation.ts index c6197e05e8..0181b90459 100644 --- a/ts/util/getConversation.ts +++ b/ts/util/getConversation.ts @@ -254,7 +254,7 @@ export function getConversation(model: ConversationModel): ConversationType { titleShortNoDefault: getTitle(attributes, { isShort: true }), typingContactIdTimestamps, searchableTitle: isMe(attributes) - ? window.i18n('icu:noteToSelf') + ? window.SignalContext.i18n('icu:noteToSelf') : getTitle(attributes), unreadCount: attributes.unreadCount || 0, unreadMentionsCount: attributes.unreadMentionsCount || 0, diff --git a/ts/util/getDraftPreview.ts b/ts/util/getDraftPreview.ts index efdeb0de70..e0d4cd17fc 100644 --- a/ts/util/getDraftPreview.ts +++ b/ts/util/getDraftPreview.ts @@ -8,6 +8,8 @@ import { hydrateRanges } from '../types/BodyRange.js'; import { isVoiceMessage } from './Attachment.js'; import { stripNewlinesForLeftPane } from './stripNewlinesForLeftPane.js'; +const { i18n } = window.SignalContext; + export function getDraftPreview( attributes: ConversationAttributesType ): DraftPreviewType { @@ -27,23 +29,23 @@ export function getDraftPreview( if (draftAttachments.length > 0) { if (isVoiceMessage(draftAttachments[0])) { return { - text: window.i18n('icu:message--getNotificationText--voice-message'), + text: i18n('icu:message--getNotificationText--voice-message'), prefix: '🎤', }; } return { - text: window.i18n('icu:Conversation--getDraftPreview--attachment'), + text: i18n('icu:Conversation--getDraftPreview--attachment'), }; } const { quotedMessageId } = attributes; if (quotedMessageId) { return { - text: window.i18n('icu:Conversation--getDraftPreview--quote'), + text: i18n('icu:Conversation--getDraftPreview--quote'), }; } return { - text: window.i18n('icu:Conversation--getDraftPreview--draft'), + text: i18n('icu:Conversation--getDraftPreview--draft'), }; } diff --git a/ts/util/getMessageAuthorText.ts b/ts/util/getMessageAuthorText.ts index 5c0eb3aa93..30e350b12f 100644 --- a/ts/util/getMessageAuthorText.ts +++ b/ts/util/getMessageAuthorText.ts @@ -32,7 +32,7 @@ export function getMessageAuthorText( // if it's outgoing, it must be self-authored const selfAuthor = isOutgoing(messageAttributes) - ? window.i18n('icu:you') + ? window.SignalContext.i18n('icu:you') : undefined; if (selfAuthor) { diff --git a/ts/util/getNotificationDataForMessage.ts b/ts/util/getNotificationDataForMessage.ts index c3b6dd2021..9bc583005f 100644 --- a/ts/util/getNotificationDataForMessage.ts +++ b/ts/util/getNotificationDataForMessage.ts @@ -60,6 +60,7 @@ import { getUserConversationId } from '../state/selectors/user.js'; import { itemStorage } from '../textsecure/Storage.js'; const log = createLogger('getNotificationDataForMessage'); +const { i18n } = window.SignalContext; function getNameForNumber(e164: string): string { const conversation = window.ConversationController.get(e164); @@ -79,7 +80,7 @@ export function getNotificationDataForMessage( if (isDeliveryIssue(attributes)) { return { emoji: '⚠️', - text: window.i18n('icu:DeliveryIssue--preview'), + text: i18n('icu:DeliveryIssue--preview'), }; } @@ -105,7 +106,7 @@ export function getNotificationDataForMessage( attributes.conversationMerge.renderInfo ), conversationTitle: conversation.getTitle(), - i18n: window.i18n, + i18n, }), }; } @@ -113,19 +114,19 @@ export function getNotificationDataForMessage( if (isChatSessionRefreshed(attributes)) { return { emoji: '🔁', - text: window.i18n('icu:ChatRefresh--notification'), + text: i18n('icu:ChatRefresh--notification'), }; } if (isUnsupportedMessage(attributes)) { return { - text: window.i18n('icu:message--getDescription--unsupported-message'), + text: i18n('icu:message--getDescription--unsupported-message'), }; } if (isGroupV1Migration(attributes)) { return { - text: window.i18n('icu:GroupV1--Migration--was-upgraded'), + text: i18n('icu:GroupV1--Migration--was-upgraded'), }; } @@ -137,7 +138,7 @@ export function getNotificationDataForMessage( } return { - text: getStringForProfileChange(change, changedContact, window.i18n), + text: getStringForProfileChange(change, changedContact, i18n), }; } @@ -149,14 +150,14 @@ export function getNotificationDataForMessage( ); const changes = GroupChange.renderChange(change, { - i18n: window.i18n, + i18n, ourAci: itemStorage.user.getCheckedAci(), ourPni: itemStorage.user.getCheckedPni(), renderContact: (conversationId: string) => { const conversation = window.ConversationController.get(conversationId); return conversation ? conversation.getTitle() - : window.i18n('icu:unknownContact'); + : i18n('icu:unknownContact'); }, renderIntl: ( key: Key, @@ -164,7 +165,7 @@ export function getNotificationDataForMessage( components: ICUStringMessageParamsByKeyType[Key] ) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any - return window.i18n(key, components as any); + return i18n(key, components as any); }, }); @@ -180,7 +181,7 @@ export function getNotificationDataForMessage( sender.title, conversation.title, sender.isMe, - window.i18n + i18n ), emoji: '💳', }; @@ -202,30 +203,24 @@ export function getNotificationDataForMessage( const isGroupConversation = isGroup(conversation.attributes); let text: string; if (event === MessageRequestResponseEvent.ACCEPT) { - text = window.i18n( - 'icu:MessageRequestResponseNotification__Message--Accepted' - ); + text = i18n('icu:MessageRequestResponseNotification__Message--Accepted'); } else if (event === MessageRequestResponseEvent.SPAM) { - text = window.i18n( - 'icu:MessageRequestResponseNotification__Message--Reported' - ); + text = i18n('icu:MessageRequestResponseNotification__Message--Reported'); } else if (event === MessageRequestResponseEvent.BLOCK) { if (isGroupConversation) { - text = window.i18n( + text = i18n( 'icu:MessageRequestResponseNotification__Message--Blocked--Group' ); } else { - text = window.i18n( - 'icu:MessageRequestResponseNotification__Message--Blocked' - ); + text = i18n('icu:MessageRequestResponseNotification__Message--Blocked'); } } else if (event === MessageRequestResponseEvent.UNBLOCK) { if (isGroupConversation) { - text = window.i18n( + text = i18n( 'icu:MessageRequestResponseNotification__Message--Unblocked--Group' ); } else { - text = window.i18n( + text = i18n( 'icu:MessageRequestResponseNotification__Message--Unblocked' ); } @@ -243,25 +238,25 @@ export function getNotificationDataForMessage( if (isTapToView(attributes)) { if (attributes.isErased) { return { - text: window.i18n('icu:message--getDescription--disappearing-media'), + text: i18n('icu:message--getDescription--disappearing-media'), }; } if (Attachment.isImage(attachments)) { return { - text: window.i18n('icu:message--getDescription--disappearing-photo'), + text: i18n('icu:message--getDescription--disappearing-photo'), emoji: '📷', }; } if (Attachment.isVideo(attachments)) { return { - text: window.i18n('icu:message--getDescription--disappearing-video'), + text: i18n('icu:message--getDescription--disappearing-video'), emoji: '🎥', }; } // There should be an image or video attachment, but we have a fallback just in // case. - return { text: window.i18n('icu:mediaMessage'), emoji: '📎' }; + return { text: i18n('icu:mediaMessage'), emoji: '📎' }; } if (isGroupUpdate(attributes)) { @@ -273,11 +268,11 @@ export function getNotificationDataForMessage( } if (groupUpdate.left === 'You') { - return { text: window.i18n('icu:youLeftTheGroup') }; + return { text: i18n('icu:youLeftTheGroup') }; } if (groupUpdate.left) { return { - text: window.i18n('icu:leftTheGroup', { + text: i18n('icu:leftTheGroup', { name: getNameForNumber(groupUpdate.left), }), }; @@ -288,10 +283,10 @@ export function getNotificationDataForMessage( } if (isMe(fromContact.attributes)) { - messages.push(window.i18n('icu:youUpdatedTheGroup')); + messages.push(i18n('icu:youUpdatedTheGroup')); } else { messages.push( - window.i18n('icu:updatedTheGroup', { + i18n('icu:updatedTheGroup', { name: fromContact.getTitle(), }) ); @@ -307,7 +302,7 @@ export function getNotificationDataForMessage( if (joinedContacts.length > 1) { messages.push( - window.i18n('icu:multipleJoinedTheGroup', { + i18n('icu:multipleJoinedTheGroup', { names: joinedWithoutMe .map(contact => contact.getTitle()) .join(', '), @@ -315,7 +310,7 @@ export function getNotificationDataForMessage( ); if (joinedWithoutMe.length < joinedContacts.length) { - messages.push(window.i18n('icu:youJoinedTheGroup')); + messages.push(i18n('icu:youJoinedTheGroup')); } } else { const joinedContact = window.ConversationController.getOrCreate( @@ -323,10 +318,10 @@ export function getNotificationDataForMessage( 'private' ); if (isMe(joinedContact.attributes)) { - messages.push(window.i18n('icu:youJoinedTheGroup')); + messages.push(i18n('icu:youJoinedTheGroup')); } else { messages.push( - window.i18n('icu:joinedTheGroup', { + i18n('icu:joinedTheGroup', { name: joinedContacts[0].getTitle(), }) ); @@ -336,22 +331,22 @@ export function getNotificationDataForMessage( if (groupUpdate.name) { messages.push( - window.i18n('icu:titleIsNow', { + i18n('icu:titleIsNow', { name: groupUpdate.name, }) ); } if (groupUpdate.avatarUpdated) { - messages.push(window.i18n('icu:updatedGroupAvatar')); + messages.push(i18n('icu:updatedGroupAvatar')); } return { text: messages.join(' ') }; } if (isEndSession(attributes)) { - return { text: window.i18n('icu:sessionEnded') }; + return { text: i18n('icu:sessionEnded') }; } if (isIncoming(attributes) && hasErrors(attributes)) { - return { text: window.i18n('icu:incomingError') }; + return { text: i18n('icu:incomingError') }; } const { body: untrimmedBody = '', bodyRanges = [] } = attributes; @@ -368,7 +363,7 @@ export function getNotificationDataForMessage( if (tooBigAttachmentCount === attachments.length) { return { emoji: '📎', - text: window.i18n('icu:message--attachmentTooBig--one'), + text: i18n('icu:message--attachmentTooBig--one'), }; } @@ -376,45 +371,41 @@ export function getNotificationDataForMessage( return { bodyRanges, emoji: '🎡', - text: body || window.i18n('icu:message--getNotificationText--gif'), + text: body || i18n('icu:message--getNotificationText--gif'), }; } if (Attachment.isImage(attachments)) { return { bodyRanges, emoji: '📷', - text: body || window.i18n('icu:message--getNotificationText--photo'), + text: body || i18n('icu:message--getNotificationText--photo'), }; } if (Attachment.isVideo(attachments)) { return { bodyRanges, emoji: '🎥', - text: body || window.i18n('icu:message--getNotificationText--video'), + text: body || i18n('icu:message--getNotificationText--video'), }; } if (Attachment.isVoiceMessage(attachment)) { return { bodyRanges, emoji: '🎤', - text: - body || - window.i18n('icu:message--getNotificationText--voice-message'), + text: body || i18n('icu:message--getNotificationText--voice-message'), }; } if (Attachment.isAudio(attachments)) { return { bodyRanges, emoji: '🔈', - text: - body || - window.i18n('icu:message--getNotificationText--audio-message'), + text: body || i18n('icu:message--getNotificationText--audio-message'), }; } return { bodyRanges, - text: body || window.i18n('icu:message--getNotificationText--file'), + text: body || i18n('icu:message--getNotificationText--file'), emoji: '📎', }; } @@ -429,7 +420,7 @@ export function getNotificationDataForMessage( log.warn('Unable to get emoji for sticker'); } return { - text: window.i18n('icu:message--getNotificationText--stickers'), + text: i18n('icu:message--getNotificationText--stickers'), emoji: dropNull(emoji), }; } @@ -446,7 +437,7 @@ export function getNotificationDataForMessage( targetedMessageId: getTargetedMessage(state)?.id, }); if (callingNotification) { - const text = getCallingNotificationText(callingNotification, window.i18n); + const text = getCallingNotificationText(callingNotification, i18n); if (text != null) { return { text, @@ -459,12 +450,12 @@ export function getNotificationDataForMessage( if (isExpirationTimerUpdate(attributes)) { const { expireTimer } = attributes.expirationTimerUpdate ?? {}; if (!expireTimer) { - return { text: window.i18n('icu:disappearingMessagesDisabled') }; + return { text: i18n('icu:disappearingMessagesDisabled') }; } return { - text: window.i18n('icu:timerSetTo', { - time: expirationTimer.format(window.i18n, expireTimer), + text: i18n('icu:timerSetTo', { + time: expirationTimer.format(i18n, expireTimer), }), }; } @@ -473,7 +464,7 @@ export function getNotificationDataForMessage( const { key_changed: identifier } = attributes; const conversation = window.ConversationController.get(identifier); return { - text: window.i18n('icu:safetyNumberChangedGroup', { + text: i18n('icu:safetyNumberChangedGroup', { name: conversation ? conversation.getTitle() : '', }), }; @@ -481,9 +472,7 @@ export function getNotificationDataForMessage( const { contact: contacts } = attributes; if (contacts && contacts.length) { return { - text: - EmbeddedContact.getName(contacts[0]) || - window.i18n('icu:unknownContact'), + text: EmbeddedContact.getName(contacts[0]) || i18n('icu:unknownContact'), emoji: '👤', }; } @@ -496,26 +485,25 @@ export function getNotificationDataForMessage( const toContact = window.ConversationController.get( attributes.conversationId ); - const recipient = - toContact?.getTitle() ?? window.i18n('icu:unknownContact'); + const recipient = toContact?.getTitle() ?? i18n('icu:unknownContact'); return { emoji, - text: window.i18n('icu:message--donation--preview--sent', { + text: i18n('icu:message--donation--preview--sent', { recipient, }), }; } const fromContact = getAuthor(attributes); - const sender = fromContact?.getTitle() ?? window.i18n('icu:unknownContact'); + const sender = fromContact?.getTitle() ?? i18n('icu:unknownContact'); return { emoji, text: giftBadge.state === GiftBadgeStates.Unopened - ? window.i18n('icu:message--donation--preview--unopened', { + ? i18n('icu:message--donation--preview--unopened', { sender, }) - : window.i18n('icu:message--donation--preview--redeemed'), + : i18n('icu:message--donation--preview--redeemed'), }; } diff --git a/ts/util/getNotificationTextForMessage.ts b/ts/util/getNotificationTextForMessage.ts index 179a4e4a57..c0b4c125bc 100644 --- a/ts/util/getNotificationTextForMessage.ts +++ b/ts/util/getNotificationTextForMessage.ts @@ -9,6 +9,8 @@ import { isConversationAccepted } from './isConversationAccepted.js'; import { strictAssert } from './assert.js'; import { itemStorage } from '../textsecure/Storage.js'; +const { i18n } = window.SignalContext; + export function getNotificationTextForMessage( attributes: ReadonlyMessageAttributesType ): string { @@ -24,7 +26,7 @@ export function getNotificationTextForMessage( ); if (!isConversationAccepted(conversation.attributes)) { - return window.i18n('icu:message--getNotificationText--messageRequest'); + return i18n('icu:message--getNotificationText--messageRequest'); } if (attributes.storyReaction) { @@ -32,7 +34,7 @@ export function getNotificationTextForMessage( const { profileName: name } = conversation.attributes; if (!name) { - return window.i18n( + return i18n( 'icu:Quote__story-reaction-notification--outgoing--nameless', { emoji: attributes.storyReaction.emoji, @@ -40,7 +42,7 @@ export function getNotificationTextForMessage( ); } - return window.i18n('icu:Quote__story-reaction-notification--outgoing', { + return i18n('icu:Quote__story-reaction-notification--outgoing', { emoji: attributes.storyReaction.emoji, name, }); @@ -52,7 +54,7 @@ export function getNotificationTextForMessage( attributes.type === 'incoming' && attributes.storyReaction.targetAuthorAci === ourAci ) { - return window.i18n('icu:Quote__story-reaction-notification--incoming', { + return i18n('icu:Quote__story-reaction-notification--incoming', { emoji: attributes.storyReaction.emoji, }); } @@ -61,7 +63,7 @@ export function getNotificationTextForMessage( return attributes.storyReaction.emoji; } - return window.i18n('icu:Quote__story-reaction--single'); + return i18n('icu:Quote__story-reaction--single'); } const result = applyRangesToText( @@ -76,7 +78,7 @@ export function getNotificationTextForMessage( // the `text`, which can contain emoji.) const shouldIncludeEmoji = Boolean(emoji) && !window.Signal.OS.isLinux(); if (shouldIncludeEmoji) { - return window.i18n('icu:message--getNotificationText--text-with-emoji', { + return i18n('icu:message--getNotificationText--text-with-emoji', { text: result.body, emoji: emoji ?? '', }); diff --git a/ts/util/getTitle.ts b/ts/util/getTitle.ts index d786be6b52..955934f51b 100644 --- a/ts/util/getTitle.ts +++ b/ts/util/getTitle.ts @@ -17,6 +17,8 @@ type TitleOptions = { ignoreNickname?: boolean; }; +const { i18n } = window.SignalContext; + export function getTitle( attributes: ConversationRenderInfoType, options?: TitleOptions @@ -27,9 +29,9 @@ export function getTitle( } if (isDirectConversation(attributes)) { - return window.i18n('icu:unknownContact'); + return i18n('icu:unknownContact'); } - return window.i18n('icu:unknownGroup'); + return i18n('icu:unknownGroup'); } export function getTitleNoDefault( diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index dce51c13e0..980497ed05 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -2317,7 +2317,7 @@ { "rule": "DOM-innerHTML", "path": "ts/windows/loading/start.ts", - "line": " message.innerHTML = window.i18n('icu:optimizingApplication');", + "line": " message.innerHTML = window.SignalContext.i18n('icu:optimizingApplication');", "reasonCategory": "usageTrusted", "updated": "2021-09-17T21:02:59.414Z" } diff --git a/ts/util/longRunningTaskWrapper.tsx b/ts/util/longRunningTaskWrapper.tsx index 14b0ebe4ff..85d53b16c8 100644 --- a/ts/util/longRunningTaskWrapper.tsx +++ b/ts/util/longRunningTaskWrapper.tsx @@ -28,6 +28,7 @@ export async function longRunningTaskWrapper({ task: () => Promise; suppressErrorDialog?: boolean; }): Promise { + const { i18n } = window.SignalContext; const idLog = `${name}/${idForLogging}`; const ONE_SECOND = 1000; const TWO_SECONDS = 2000; @@ -41,9 +42,9 @@ export async function longRunningTaskWrapper({ progressRoot = createRoot(progressNode); progressRoot.render( - + - + diff --git a/ts/util/showConfirmationDialog.tsx b/ts/util/showConfirmationDialog.tsx index f28457d67b..03c9c583de 100644 --- a/ts/util/showConfirmationDialog.tsx +++ b/ts/util/showConfirmationDialog.tsx @@ -47,6 +47,8 @@ function removeConfirmationDialog() { export function showConfirmationDialog( options: ConfirmationDialogViewProps ): void { + const { i18n } = window.SignalContext; + if (confirmationDialogRoot) { removeConfirmationDialog(); } @@ -61,7 +63,7 @@ export function showConfirmationDialog( confirmationDialogRoot = createRoot(confirmationDialogViewNode); confirmationDialogRoot.render( - + { if (options.reject) { options.reject( diff --git a/ts/window.d.ts b/ts/window.d.ts index 7b75c524ab..1ea07a177a 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -13,11 +13,7 @@ import type { MochaOptions } from 'mocha'; import type { IPCRequest as IPCChallengeRequest } from './challenge.js'; import type AccountManager from './textsecure/AccountManager.js'; import type { OSType } from './util/os/shared.js'; -import type { - LocalizerType, - SystemThemeType, - ThemeType, -} from './types/Util.js'; +import type { SystemThemeType, ThemeType } from './types/Util.js'; import type { Receipt } from './types/Receipt.js'; import type { ConversationController } from './ConversationController.js'; import type { ReduxActions } from './state/types.js'; @@ -33,8 +29,6 @@ import type { WindowsNotificationData } from './services/notifications.js'; import type { QueryStatsOptions } from './sql/main.js'; import type { SocketStatuses } from './textsecure/SocketManager.js'; -export { Long } from 'long'; - export type IPCType = { addSetupMenuItems: () => void; clearAllWindowsNotifications: () => Promise; @@ -166,7 +160,6 @@ declare global { initialTheme?: ThemeType; nodeSetImmediate: typeof setImmediate; platform: string; - preloadedImages: Array; setImmediate: typeof setImmediate; sendChallengeRequest: (request: IPCChallengeRequest) => void; systemTheme: SystemThemeType; @@ -184,7 +177,6 @@ declare global { Events: IPCEventsType; MessageCache: MessageCache; Whisper: WhisperType; - i18n: LocalizerType; // Note: used in background.html, and not type-checked startApp: () => void; diff --git a/ts/windows/about/app.tsx b/ts/windows/about/app.tsx index 6a402a3a4f..b9f196b505 100644 --- a/ts/windows/about/app.tsx +++ b/ts/windows/about/app.tsx @@ -4,13 +4,14 @@ import React, { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; +import '../sandboxedInit.js'; import { About } from '../../components/About.js'; -import { i18n } from '../sandboxedInit.js'; import { strictAssert } from '../../util/assert.js'; import { FunDefaultEnglishEmojiLocalizationProvider } from '../../components/fun/FunEmojiLocalizationProvider.js'; import { AxoProvider } from '../../axo/AxoProvider.js'; const { AboutWindowProps } = window.Signal; +const { i18n } = window.SignalContext; strictAssert(AboutWindowProps, 'window values not provided'); @@ -19,7 +20,9 @@ strictAssert(app != null, 'No #app'); createRoot(app).render( - + window.SignalContext.executeMenuRole('close')} diff --git a/ts/windows/context.ts b/ts/windows/context.ts index 6c300ff5ea..f2c7fe2574 100644 --- a/ts/windows/context.ts +++ b/ts/windows/context.ts @@ -35,6 +35,7 @@ export type MinimalSignalContextType = { getI18nAvailableLocales: () => ReadonlyArray; getI18nLocale: LocalizerType['getLocale']; getI18nLocaleMessages: LocalizerType['getLocaleMessages']; + i18n: LocalizerType; getLocaleDisplayNames: () => Record>; getCountryDisplayNames: () => Record>; getResolvedMessagesLocaleDirection: () => LocaleDirection; @@ -65,8 +66,6 @@ export type MinimalSignalContextType = { export type SignalContextType = { bytes: Bytes; crypto: Crypto; - i18n: LocalizerType; - renderWindow?: () => void; setIsCallActive: (isCallActive: boolean) => unknown; timers: Timers; } & MinimalSignalContextType; @@ -83,4 +82,3 @@ export const SignalContext: SignalContextType = { }; window.SignalContext = SignalContext; -window.i18n = SignalContext.i18n; diff --git a/ts/windows/debuglog/app.tsx b/ts/windows/debuglog/app.tsx index 91590c0528..90368511b4 100644 --- a/ts/windows/debuglog/app.tsx +++ b/ts/windows/debuglog/app.tsx @@ -3,13 +3,14 @@ import React, { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; +import '../sandboxedInit.js'; import { DebugLogWindow } from '../../components/DebugLogWindow.js'; import { FunDefaultEnglishEmojiLocalizationProvider } from '../../components/fun/FunEmojiLocalizationProvider.js'; -import { i18n } from '../sandboxedInit.js'; import { strictAssert } from '../../util/assert.js'; import { AxoProvider } from '../../axo/AxoProvider.js'; const { DebugLogWindowProps } = window.Signal; +const { i18n } = window.SignalContext; strictAssert(DebugLogWindowProps, 'window values not provided'); @@ -18,7 +19,9 @@ strictAssert(app != null, 'No #app'); createRoot(app).render( - + window.SignalContext.executeMenuRole('close')} diff --git a/ts/windows/init.ts b/ts/windows/init.ts deleted file mode 100644 index 765238e3eb..0000000000 --- a/ts/windows/init.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2021 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -document.body.classList.add(window.SignalContext.OS.getClassName()); - -if (window.SignalContext.renderWindow) { - window.SignalContext.renderWindow(); -} else { - throw new Error('renderWindow is undefined!'); -} diff --git a/ts/windows/loading/start.ts b/ts/windows/loading/start.ts index c6208adda2..14a681d658 100644 --- a/ts/windows/loading/start.ts +++ b/ts/windows/loading/start.ts @@ -1,14 +1,7 @@ // Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import { setupI18n } from '../../util/setupI18n.js'; - -window.i18n = setupI18n( - window.SignalContext.getI18nLocale(), - window.SignalContext.getI18nLocaleMessages() -); - const message = document.getElementById('message'); if (message) { - message.innerHTML = window.i18n('icu:optimizingApplication'); + message.innerHTML = window.SignalContext.i18n('icu:optimizingApplication'); } diff --git a/ts/windows/main/phase1-ipc.ts b/ts/windows/main/phase1-ipc.ts index 6e570dc7e0..760bf75e58 100644 --- a/ts/windows/main/phase1-ipc.ts +++ b/ts/windows/main/phase1-ipc.ts @@ -43,11 +43,8 @@ const { groupBy, mapValues } = lodash; const log = createLogger('phase1-ipc'); -// It is important to call this as early as possible -window.i18n = SignalContext.i18n; - // We are comfortable doing this because we verified the type on the other side! -const { config } = window.SignalContext; +const { config } = SignalContext; // Flags for testing const Flags = { diff --git a/ts/windows/main/phase2-dependencies.ts b/ts/windows/main/phase2-dependencies.ts index 67abb13939..c9a1196462 100644 --- a/ts/windows/main/phase2-dependencies.ts +++ b/ts/windows/main/phase2-dependencies.ts @@ -20,16 +20,16 @@ initializeLogging(); window.nodeSetImmediate = setImmediate; -const { config } = window.SignalContext; +const { config, i18n } = window.SignalContext; const { resolvedTranslationsLocale, preferredSystemLocales, localeOverride } = config; moment.updateLocale(localeOverride ?? resolvedTranslationsLocale, { relativeTime: { - s: window.i18n('icu:timestamp_s'), - m: window.i18n('icu:timestamp_m'), - h: window.i18n('icu:timestamp_h'), + s: i18n('icu:timestamp_s'), + m: i18n('icu:timestamp_m'), + h: i18n('icu:timestamp_h'), }, }); moment.locale( diff --git a/ts/windows/minimalContext.ts b/ts/windows/minimalContext.ts index a821a78448..710bfebc15 100644 --- a/ts/windows/minimalContext.ts +++ b/ts/windows/minimalContext.ts @@ -15,6 +15,7 @@ import { activeWindowService } from '../context/activeWindowService.js'; import { config } from '../context/config.js'; import { createNativeThemeListener } from '../context/createNativeThemeListener.js'; import { createSetting } from '../util/preload.js'; +import { setupI18n } from '../util/setupI18n.js'; import { environment } from '../context/environment.js'; import { localeDisplayNames, @@ -67,6 +68,7 @@ export const MinimalSignalContext: MinimalSignalContextType = { getI18nAvailableLocales: () => config.availableLocales, getI18nLocale: () => config.resolvedTranslationsLocale, getI18nLocaleMessages: () => localeMessages, + i18n: setupI18n(config.resolvedTranslationsLocale, localeMessages), getLocaleDisplayNames: () => localeDisplayNames, getCountryDisplayNames: () => countryDisplayNames, diff --git a/ts/windows/permissions/app.tsx b/ts/windows/permissions/app.tsx index c0ae315ddc..f69b10a76b 100644 --- a/ts/windows/permissions/app.tsx +++ b/ts/windows/permissions/app.tsx @@ -4,13 +4,14 @@ import React, { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; +import '../sandboxedInit.js'; import { PermissionsPopup } from '../../components/PermissionsPopup.js'; -import { i18n } from '../sandboxedInit.js'; import { strictAssert } from '../../util/assert.js'; import { FunDefaultEnglishEmojiLocalizationProvider } from '../../components/fun/FunEmojiLocalizationProvider.js'; import { AxoProvider } from '../../axo/AxoProvider.js'; const { PermissionsWindowProps } = window.Signal; +const { i18n } = window.SignalContext; strictAssert(PermissionsWindowProps, 'window values not provided'); @@ -32,7 +33,9 @@ strictAssert(app != null, 'No #app'); createRoot(app).render( - + - +