From 1bc85b3f0af34ccebda5cd75ba21b175d53ff8fc Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Wed, 23 Sep 2026 19:29:52 -0300 Subject: [PATCH 1/5] chore: Fix localization issues and add missing strings --- .../UniversalSearchController.ts | 3 +- .../UniversalSearch/UniversalSearchShell.tsx | 66 ++++++++++++------- ...registerUniversalSearchKeyboardHandlers.ts | 9 +-- .../NotesOptions/PlainNoteOptions.tsx | 3 +- .../Subscription/SubscriptionStatusText.tsx | 53 ++++----------- .../Panes/Backups/Files/BackupsDropZone.tsx | 20 ++++-- .../Panes/Listed/ListedSunsettingBanner.tsx | 21 +++--- .../Components/SearchBar/SearchBar.tsx | 2 +- .../EnhancedSearchOptionsContent.tsx | 15 +++-- .../SearchOptions/SearchBubbles.tsx | 15 ++++- .../SearchOptions/SearchFilterSheet.tsx | 9 ++- .../SearchOptions/SearchTagFilters.tsx | 3 +- 12 files changed, 126 insertions(+), 93 deletions(-) diff --git a/packages/web/src/javascripts/Components/NoteView/UniversalSearch/UniversalSearchController.ts b/packages/web/src/javascripts/Components/NoteView/UniversalSearch/UniversalSearchController.ts index bdd69f04b87..a840ec8adfb 100644 --- a/packages/web/src/javascripts/Components/NoteView/UniversalSearch/UniversalSearchController.ts +++ b/packages/web/src/javascripts/Components/NoteView/UniversalSearch/UniversalSearchController.ts @@ -1,4 +1,5 @@ import { action, computed, makeObservable, observable, runInAction } from 'mobx' +import { c } from 'ttag' import { UniversalSearchProvider, UniversalSearchResult, @@ -32,7 +33,7 @@ function errorMessage(error: unknown): string { return error.message } - return 'Search failed' + return c('B3.Notes.EditorToolbar.Error').t`Search failed` } type SetSearchResultsOptions = { diff --git a/packages/web/src/javascripts/Components/NoteView/UniversalSearch/UniversalSearchShell.tsx b/packages/web/src/javascripts/Components/NoteView/UniversalSearch/UniversalSearchShell.tsx index 33540773b46..f9870f07572 100644 --- a/packages/web/src/javascripts/Components/NoteView/UniversalSearch/UniversalSearchShell.tsx +++ b/packages/web/src/javascripts/Components/NoteView/UniversalSearch/UniversalSearchShell.tsx @@ -2,6 +2,7 @@ import { ArrowDownIcon, ArrowRightIcon, ArrowUpIcon, CloseIcon } from '@standard import { classNames } from '@standardnotes/utils' import { observer } from 'mobx-react-lite' import { KeyboardEvent, useEffect, useRef } from 'react' +import { c } from 'ttag' import Button from '../../Button/Button' import Icon from '../../Icon/Icon' import DecoratedInput from '../../Input/DecoratedInput' @@ -22,11 +23,11 @@ interface UniversalSearchShellProps { function statusLabel(controller: UniversalSearchController): string { if (controller.status === 'loading') { - return 'Loading' + return c('B2.NavSharedUI.Info').t`Loading` } if (controller.status === 'error') { - return controller.error || 'Error' + return controller.error || c('B2.NavSharedUI.Label').t`Error` } if (!controller.query) { @@ -129,8 +130,12 @@ export const UniversalSearchShell = observer(function UniversalSearchShell {controller.isReplaceMode ? ( @@ -149,7 +154,7 @@ export const UniversalSearchShell = observer(function UniversalSearchShell
{statusLabel(controller)}
, @@ -173,23 +178,29 @@ export const UniversalSearchShell = observer(function UniversalSearchShell Aa + {c('B3.Notes.EditorToolbar.Label').t`Case sensitive`} @@ -197,16 +208,20 @@ export const UniversalSearchShell = observer(function UniversalSearchShell @@ -215,7 +230,7 @@ export const UniversalSearchShell = observer(function UniversalSearchShell { controller.setReplaceQuery(event.target.value) @@ -224,23 +239,23 @@ export const UniversalSearchShell = observer(function UniversalSearchShell )} @@ -252,17 +267,20 @@ export const UniversalSearchShell = observer(function UniversalSearchShell controller.setShouldHighlightAll(event.target.checked)} disabled={!canHighlightAll} - aria-label="Highlight all results" + aria-label={c('B3.Notes.EditorToolbar.Label').t`Highlight all results`} /> -
Highlight all results
+
{c('B3.Notes.EditorToolbar.Label').t`Highlight all results`}
{!canHighlightAll && ( - diff --git a/packages/web/src/javascripts/Components/NoteView/UniversalSearch/registerUniversalSearchKeyboardHandlers.ts b/packages/web/src/javascripts/Components/NoteView/UniversalSearch/registerUniversalSearchKeyboardHandlers.ts index c3131ef2ced..5565b46dbf1 100644 --- a/packages/web/src/javascripts/Components/NoteView/UniversalSearch/registerUniversalSearchKeyboardHandlers.ts +++ b/packages/web/src/javascripts/Components/NoteView/UniversalSearch/registerUniversalSearchKeyboardHandlers.ts @@ -7,6 +7,7 @@ import { UNIVERSAL_TOGGLE_SEARCH, } from '@standardnotes/ui-services' import { Disposer } from '@/Types/Disposer' +import { c } from 'ttag' import { UniversalSearchController } from './UniversalSearchController' export function registerUniversalSearchKeyboardHandlers( @@ -17,7 +18,7 @@ export function registerUniversalSearchKeyboardHandlers( { command: UNIVERSAL_TOGGLE_SEARCH, category: 'Search', - description: 'Search in current note', + description: c('B3.Notes.EditorToolbar.Action').t`Search in current note`, onKeyDown: (event) => { event.preventDefault() event.stopPropagation() @@ -32,7 +33,7 @@ export function registerUniversalSearchKeyboardHandlers( { command: UNIVERSAL_SEARCH_TOGGLE_REPLACE_MODE, category: 'Search', - description: 'Search and replace in current note', + description: c('B3.Notes.EditorToolbar.Action').t`Search and replace in current note`, onKeyDown: (event) => { if (!controller.canReplace) { return @@ -65,7 +66,7 @@ export function registerUniversalSearchKeyboardHandlers( { command: UNIVERSAL_SEARCH_NEXT_RESULT, category: 'Search', - description: 'Go to next search result', + description: c('B3.Notes.EditorToolbar.Action').t`Go to next search result`, onKeyDown(event) { if (!controller.isOpen) { return @@ -79,7 +80,7 @@ export function registerUniversalSearchKeyboardHandlers( { command: UNIVERSAL_SEARCH_PREVIOUS_RESULT, category: 'Search', - description: 'Go to previous search result', + description: c('B3.Notes.EditorToolbar.Action').t`Go to previous search result`, onKeyDown(event) { if (!controller.isOpen) { return diff --git a/packages/web/src/javascripts/Components/NotesOptions/PlainNoteOptions.tsx b/packages/web/src/javascripts/Components/NotesOptions/PlainNoteOptions.tsx index 5c52d614c55..3b2ed94d362 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/PlainNoteOptions.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/PlainNoteOptions.tsx @@ -5,6 +5,7 @@ import { iconClass } from './ClassNames' import MenuSection from '../Menu/MenuSection' import { UNIVERSAL_TOGGLE_SEARCH } from '@standardnotes/ui-services' import { useMemo, useCallback } from 'react' +import { c } from 'ttag' import { useKeyboardService } from '../KeyboardServiceProvider' type Props = { @@ -28,7 +29,7 @@ const PlainNoteOptions = ({ closeMenu }: Props) => { - Find in note + {c('B4.Notes.EditorOptions.Action').t`Find in note`} {findShortcut && } diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Subscription/SubscriptionStatusText.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Subscription/SubscriptionStatusText.tsx index 7560107e6d1..5a8081e0596 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Subscription/SubscriptionStatusText.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Subscription/SubscriptionStatusText.tsx @@ -16,6 +16,10 @@ const SubscriptionStatusText = () => { const isSharedSubscription = application.subscriptionController.isSharedSubscription const expirationDateString = userSubscriptionExpirationDate?.toLocaleString() + const appNameBold = {AppName} + const subscriptionTierBold = userSubscriptionName ? {userSubscriptionName} : null + const expirationDateBold = {expirationDateString} + const sharedMessage = isSharedSubscription ? ( <>
@@ -28,23 +32,11 @@ const SubscriptionStatusText = () => { if (isUserSubscriptionCanceled) { return ( - {c('B6.Preferences.Subscription.Info').t`Your`}{' '} - - {AppName} - {userSubscriptionName ? ' ' : ''} - {userSubscriptionName} - {' '} - {c('B6.Preferences.Subscription.Info').t`subscription has been canceled`}{' '} - {isUserSubscriptionExpired ? ( - - {c('B6.Preferences.Subscription.Info').t`and expired on`} {expirationDateString} - - ) : ( - - {c('B6.Preferences.Subscription.Info').t`but will remain valid until`} {expirationDateString} - - )} - {c('B6.Preferences.Subscription.Info').t`. You may resubscribe below if you wish.`} + {isUserSubscriptionExpired + ? c('B6.Preferences.Subscription.Info') + .jt`Your ${appNameBold}${subscriptionTierBold} subscription has been canceled and expired on ${expirationDateBold}. You may resubscribe below if you wish.` + : c('B6.Preferences.Subscription.Info') + .jt`Your ${appNameBold}${subscriptionTierBold} subscription has been canceled but will remain valid until ${expirationDateBold}. You may resubscribe below if you wish.`} {sharedMessage} ) @@ -53,17 +45,8 @@ const SubscriptionStatusText = () => { if (isUserSubscriptionExpired) { return ( - {c('B6.Preferences.Subscription.Info').t`Your`}{' '} - - {AppName} - {userSubscriptionName ? ' ' : ''} - {userSubscriptionName} - {' '} - {c('B6.Preferences.Subscription.Info').t`subscription`}{' '} - - {c('B6.Preferences.Subscription.Info').t`expired on`} {expirationDateString} - - {c('B6.Preferences.Subscription.Info').t`. You may resubscribe below if you wish.`} + {c('B6.Preferences.Subscription.Info') + .jt`Your ${appNameBold}${subscriptionTierBold} subscription expired on ${expirationDateBold}. You may resubscribe below if you wish.`} {sharedMessage} ) @@ -71,17 +54,9 @@ const SubscriptionStatusText = () => { return ( - {c('B6.Preferences.Subscription.Info').t`Your`}{' '} - - {AppName} - {userSubscriptionName ? ' ' : ''} - {userSubscriptionName} - {' '} - {c('B6.Preferences.Subscription.Info').t`subscription will be`}{' '} - - {c('B6.Preferences.Subscription.Info').t`renewed on`} {expirationDateString} - - .{sharedMessage} + {c('B6.Preferences.Subscription.Info') + .jt`Your ${appNameBold}${subscriptionTierBold} subscription will be renewed on ${expirationDateBold}.`} + {sharedMessage} ) } diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Backups/Files/BackupsDropZone.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Backups/Files/BackupsDropZone.tsx index 050c4fda274..1040bd871aa 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Backups/Files/BackupsDropZone.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Backups/Files/BackupsDropZone.tsx @@ -1,7 +1,14 @@ import { Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content' import { useCallback, useEffect, useMemo, useState, FunctionComponent } from 'react' import Button from '@/Components/Button/Button' -import { FileBackupMetadataFile, FileBackupsConstantsV1, FileItem, FileHandleRead } from '@standardnotes/snjs' +import { jtString } from '@standardnotes/features' +import { + escapeHtmlString, + FileBackupMetadataFile, + FileBackupsConstantsV1, + FileItem, + FileHandleRead, +} from '@standardnotes/snjs' import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator' import Icon from '@/Components/Icon/Icon' import { ClassicFileReader, StreamingFileApi } from '@standardnotes/filepicker' @@ -52,9 +59,12 @@ const BackupsDropZone: FunctionComponent = ({ application }) => { if (result === 'success') { const decryptedFileName = decryptedFileItem.name + const decryptedFileNameBold = `${escapeHtmlString(decryptedFileName)}` void application.alerts.alert( - c('B6.Preferences.Backups.Info') - .t`${decryptedFileName} has been successfully decrypted and saved to your chosen directory.`, + jtString( + c('B6.Preferences.Backups.Info') + .jt`${decryptedFileNameBold} has been successfully decrypted and saved to your chosen directory.`, + ), ) setBinaryFile(undefined) setDecryptedFileItem(undefined) @@ -143,12 +153,14 @@ const BackupsDropZone: FunctionComponent = ({ application }) => { } }, [handleDragIn, handleDrop, handleDragOver, handleDragOut]) + const metadataFileName = {FileBackupsConstantsV1.MetadataFileName} + if (!droppedFile) { return ( <> {c('B6.Preferences.Backups.Info') - .t`To decrypt a backup file, drag and drop the file's respective metadata.sn.json file here or select it below.`} + .jt`To decrypt a backup file, drag and drop the file's respective ${metadataFileName} file here or select it below.`} diff --git a/packages/web/src/javascripts/Components/RevisionHistoryModal/RevisionContentLocked.tsx b/packages/web/src/javascripts/Components/RevisionHistoryModal/RevisionContentLocked.tsx index daab924e91b..5f2c56d7d83 100644 --- a/packages/web/src/javascripts/Components/RevisionHistoryModal/RevisionContentLocked.tsx +++ b/packages/web/src/javascripts/Components/RevisionHistoryModal/RevisionContentLocked.tsx @@ -26,7 +26,7 @@ const getPremiumContentCopy = (planName: string | undefined) => { const RevisionContentLocked: FunctionComponent = () => { const application = useApplication() - let planName = 'free' + let planName: string | undefined if (application.subscriptions.hasOnlineSubscription()) { if (!application.subscriptions.isUserSubscriptionCanceled && !application.subscriptions.isUserSubscriptionExpired) { planName = application.subscriptions.userSubscriptionName diff --git a/packages/web/src/javascripts/Components/SuperEditor/Plugins/EncryptedFilePlugin/Nodes/FileComponent.tsx b/packages/web/src/javascripts/Components/SuperEditor/Plugins/EncryptedFilePlugin/Nodes/FileComponent.tsx index 247110048f7..a10b4a1d5aa 100644 --- a/packages/web/src/javascripts/Components/SuperEditor/Plugins/EncryptedFilePlugin/Nodes/FileComponent.tsx +++ b/packages/web/src/javascripts/Components/SuperEditor/Plugins/EncryptedFilePlugin/Nodes/FileComponent.tsx @@ -142,8 +142,7 @@ function FileComponent({
- {c('B4.Notes.EditingUI.Status').t`Uploading file "`} - {uploadProgress.file.name}"... ({progress}%) + {c('B4.Notes.EditingUI.Status').jt`Uploading file "${uploadProgress.file.name}" (${progress}%)`}
-
- {c('B4.Notes.EditingUI.Label').t`Unable to find file`} {fileUuid} -
+
{c('B4.Notes.EditingUI.Label').jt`Unable to find file ${fileUuid}`}
) } From 34b42d55a2083e37031cfab62397e93b73fb1a5f Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Tue, 29 Sep 2026 11:35:54 -0300 Subject: [PATCH 4/5] chore: fix eslint error --- .../Preferences/Panes/Listed/ListedSunsettingBanner.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Listed/ListedSunsettingBanner.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Listed/ListedSunsettingBanner.tsx index e8bf75739f7..ef18dce302b 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Listed/ListedSunsettingBanner.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Listed/ListedSunsettingBanner.tsx @@ -20,8 +20,7 @@ const LearnMoreLink = () => { const ListedSunsettingBanner = ({ variant = 'pane' }: Props) => { const message = variant === 'menu' - ? c('B6.Preferences.Listed.Info') - .jt`${ListedName} will permanently shut down on December 31, 2026.` + ? c('B6.Preferences.Listed.Info').jt`${ListedName} will permanently shut down on December 31, 2026.` : c('B6.Preferences.Listed.Info') .jt`Note: The ${ListedName} platform will permanently shut down December 31, 2026. Your data published on ${ListedName} will still be available in your personal ${AppName} account.` From 54b4440977d410470edd6189f34407faa89e5e98 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Tue, 29 Sep 2026 11:52:40 -0300 Subject: [PATCH 5/5] chore: fix eslint error --- packages/desktop/app/javascripts/Main/Menus/Menus.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/desktop/app/javascripts/Main/Menus/Menus.ts b/packages/desktop/app/javascripts/Main/Menus/Menus.ts index 5e01fa50eab..51a5c54147e 100644 --- a/packages/desktop/app/javascripts/Main/Menus/Menus.ts +++ b/packages/desktop/app/javascripts/Main/Menus/Menus.ts @@ -242,10 +242,7 @@ function editMenu( function macSpeechMenu(): MenuItemConstructorOptions { return { label: str().speech, - submenu: [ - menuRole(str().startSpeaking, Roles.StartSeeking), - menuRole(str().stopSpeaking, Roles.StopSeeking), - ], + submenu: [menuRole(str().startSpeaking, Roles.StartSeeking), menuRole(str().stopSpeaking, Roles.StopSeeking)], } }