diff --git a/packages/desktop-client/src/components/FatalError.tsx b/packages/desktop-client/src/components/FatalError.tsx
index 663fd6abb4d47162ea2fbe256b1bc786f005ede2..682ba97aa242cdd73c840fa071c980363154131a 100644
--- a/packages/desktop-client/src/components/FatalError.tsx
+++ b/packages/desktop-client/src/components/FatalError.tsx
@@ -1,4 +1,5 @@
 import React, { useState, type ReactNode } from 'react';
+import { useTranslation, Trans } from 'react-i18next';
 
 import { LazyLoadFailedError } from 'loot-core/src/shared/errors';
 
@@ -32,10 +33,12 @@ function RenderSimple({ error }: RenderSimpleProps) {
     // IndexedDB wasn't able to open the database
     msg = (
       <Text>
-        Your browser doesn’t support IndexedDB in this environment, a feature
-        that Actual requires to run. This might happen if you are in private
-        browsing mode. Please try a different browser or turn off private
-        browsing.
+        <Trans>
+          Your browser doesn’t support IndexedDB in this environment, a feature
+          that Actual requires to run. This might happen if you are in private
+          browsing mode. Please try a different browser or turn off private
+          browsing.
+        </Trans>
       </Text>
     );
   } else if (
@@ -45,18 +48,20 @@ function RenderSimple({ error }: RenderSimpleProps) {
     // SharedArrayBuffer isn't available
     msg = (
       <Text>
-        Actual requires access to <code>SharedArrayBuffer</code> in order to
-        function properly. If you’re seeing this error, either your browser does
-        not support <code>SharedArrayBuffer</code>, or your server is not
-        sending the appropriate headers, or you are not using HTTPS. See{' '}
-        <Link
-          variant="external"
-          linkColor="muted"
-          to="https://actualbudget.org/docs/troubleshooting/shared-array-buffer"
-        >
-          our troubleshooting documentation
-        </Link>{' '}
-        to learn more. <SharedArrayBufferOverride />
+        <Trans>
+          Actual requires access to <code>SharedArrayBuffer</code> in order to
+          function properly. If you’re seeing this error, either your browser
+          does not support <code>SharedArrayBuffer</code>, or your server is not
+          sending the appropriate headers, or you are not using HTTPS. See{' '}
+          <Link
+            variant="external"
+            linkColor="muted"
+            to="https://actualbudget.org/docs/troubleshooting/shared-array-buffer"
+          >
+            our troubleshooting documentation
+          </Link>{' '}
+          to learn more. <SharedArrayBufferOverride />
+        </Trans>
       </Text>
     );
   } else {
@@ -64,7 +69,11 @@ function RenderSimple({ error }: RenderSimpleProps) {
     // user something at least so they aren't looking at a blank
     // screen
     msg = (
-      <Text>There was a problem loading the app in this browser version.</Text>
+      <Text>
+        <Trans>
+          There was a problem loading the app in this browser version.
+        </Trans>
+      </Text>
     );
   }
 
@@ -78,15 +87,17 @@ function RenderSimple({ error }: RenderSimpleProps) {
     >
       <Text>{msg}</Text>
       <Text>
-        Please get{' '}
-        <Link
-          variant="external"
-          linkColor="muted"
-          to="https://actualbudget.org/contact"
-        >
-          in touch
-        </Link>{' '}
-        for support
+        <Trans>
+          Please get{' '}
+          <Link
+            variant="external"
+            linkColor="muted"
+            to="https://actualbudget.org/contact"
+          >
+            in touch
+          </Link>{' '}
+          for support
+        </Trans>
       </Text>
     </Stack>
   );
@@ -102,10 +113,12 @@ function RenderLazyLoadError() {
       }}
     >
       <Text>
-        There was a problem loading one of the chunks of the application. Please
-        reload the page and try again. If the issue persists - there might be an
-        issue with either your internet connection and/or the server where the
-        app is hosted.
+        <Trans>
+          There was a problem loading one of the chunks of the application.
+          Please reload the page and try again. If the issue persists - there
+          might be an issue with either your internet connection and/or the
+          server where the app is hosted.
+        </Trans>
       </Text>
     </Stack>
   );
@@ -114,13 +127,17 @@ function RenderLazyLoadError() {
 function RenderUIError() {
   return (
     <>
-      <Paragraph>There was an unrecoverable error in the UI. Sorry!</Paragraph>
       <Paragraph>
-        If this error persists, please get{' '}
-        <Link variant="external" to="https://actualbudget.org/contact">
-          in touch
-        </Link>{' '}
-        so it can be investigated.
+        <Trans>There was an unrecoverable error in the UI. Sorry!</Trans>
+      </Paragraph>
+      <Paragraph>
+        <Trans>
+          If this error persists, please get{' '}
+          <Link variant="external" to="https://actualbudget.org/contact">
+            in touch
+          </Link>{' '}
+          so it can be investigated.
+        </Trans>
       </Paragraph>
     </>
   );
@@ -133,11 +150,13 @@ function SharedArrayBufferOverride() {
   return expanded ? (
     <>
       <Paragraph style={{ marginTop: 10 }}>
-        Actual uses <code>SharedArrayBuffer</code> to allow usage from multiple
-        tabs at once and to ensure correct behavior when switching files. While
-        it can run without access to <code>SharedArrayBuffer</code>, you may
-        encounter data loss or notice multiple budget files being merged with
-        each other.
+        <Trans>
+          Actual uses <code>SharedArrayBuffer</code> to allow usage from
+          multiple tabs at once and to ensure correct behavior when switching
+          files. While it can run without access to
+          <code>SharedArrayBuffer</code>, you may encounter data loss or notice
+          multiple budget files being merged with each other.
+        </Trans>
       </Paragraph>
       <label
         style={{ display: 'flex', alignItems: 'center', marginBottom: 10 }}
@@ -146,7 +165,9 @@ function SharedArrayBufferOverride() {
           checked={understand}
           onChange={() => setUnderstand(!understand)}
         />{' '}
-        I understand the risks, run Actual in the unsupported fallback mode
+        <Trans>
+          I understand the risks, run Actual in the unsupported fallback mode
+        </Trans>
       </label>
       <Button
         isDisabled={!understand}
@@ -155,7 +176,7 @@ function SharedArrayBufferOverride() {
           window.location.reload();
         }}
       >
-        Open Actual
+        <Trans>Open Actual</Trans>
       </Button>
     </>
   ) : (
@@ -164,12 +185,14 @@ function SharedArrayBufferOverride() {
       onClick={() => setExpanded(true)}
       style={{ marginLeft: 5 }}
     >
-      Advanced options
+      <Trans>Advanced options</Trans>
     </Link>
   );
 }
 
 export function FatalError({ error }: FatalErrorProps) {
+  const { t } = useTranslation();
+
   const [showError, setShowError] = useState(false);
 
   const showSimpleRender = 'type' in error && error.type === 'app-init-failure';
@@ -177,7 +200,9 @@ export function FatalError({ error }: FatalErrorProps) {
 
   return (
     <Modal name="fatal-error" isDismissable={false}>
-      <ModalHeader title={isLazyLoadError ? 'Loading Error' : 'Fatal Error'} />
+      <ModalHeader
+        title={isLazyLoadError ? t('Loading Error') : t('Fatal Error')}
+      />
       <View
         style={{
           maxWidth: 500,
@@ -192,11 +217,13 @@ export function FatalError({ error }: FatalErrorProps) {
         )}
 
         <Paragraph>
-          <Button onPress={() => window.Actual?.relaunch()}>Restart app</Button>
+          <Button onPress={() => window.Actual?.relaunch()}>
+            <Trans>Restart app</Trans>
+          </Button>
         </Paragraph>
         <Paragraph isLast={true} style={{ fontSize: 11 }}>
           <Link variant="text" onClick={() => setShowError(state => !state)}>
-            Show Error
+            <Trans>Show Error</Trans>
           </Link>
           {showError && (
             <Block
diff --git a/packages/desktop-client/src/components/LoggedInUser.tsx b/packages/desktop-client/src/components/LoggedInUser.tsx
index 0df0d616f082e7f692c75d45e0210e3e487c1b22..0db60ec4c5ba0a02541140fee746e8089bd6bae2 100644
--- a/packages/desktop-client/src/components/LoggedInUser.tsx
+++ b/packages/desktop-client/src/components/LoggedInUser.tsx
@@ -1,5 +1,6 @@
 // @ts-strict-ignore
 import React, { useState, useEffect, useRef } from 'react';
+import { Trans, useTranslation } from 'react-i18next';
 import { useSelector } from 'react-redux';
 
 import { type State } from 'loot-core/src/client/state-types';
@@ -24,6 +25,8 @@ export function LoggedInUser({
   style,
   color,
 }: LoggedInUserProps) {
+  const { t } = useTranslation();
+
   const userData = useSelector((state: State) => state.user.data);
   const { getUserData, signOut, closeBudget } = useActions();
   const [loading, setLoading] = useState(true);
@@ -64,14 +67,14 @@ export function LoggedInUser({
 
   function serverMessage() {
     if (!serverUrl) {
-      return 'No server';
+      return t('No server');
     }
 
     if (userData?.offline) {
-      return 'Server offline';
+      return t('Server offline');
     }
 
-    return 'Server online';
+    return t('Server online');
   }
 
   if (hideIfNoServer && !serverUrl) {
@@ -88,7 +91,7 @@ export function LoggedInUser({
           ...style,
         }}
       >
-        Connecting...
+        <Trans>Connecting...</Trans>
       </Text>
     );
   }
@@ -115,12 +118,14 @@ export function LoggedInUser({
             serverUrl &&
               !userData?.offline && {
                 name: 'change-password',
-                text: 'Change password',
+                text: t('Change password'),
               },
-            serverUrl && { name: 'sign-out', text: 'Sign out' },
+            serverUrl && { name: 'sign-out', text: t('Sign out') },
             {
               name: 'config-server',
-              text: serverUrl ? 'Change server URL' : 'Start using a server',
+              text: serverUrl
+                ? t('Change server URL')
+                : t('Start using a server'),
             },
           ]}
         />
diff --git a/packages/desktop-client/src/components/gocardless/GoCardlessLink.tsx b/packages/desktop-client/src/components/gocardless/GoCardlessLink.tsx
index a40f31ef01f1be8b941e3711637d755334a9c24e..2a3312242e90336115bb9faea06c0f3866fc32e2 100644
--- a/packages/desktop-client/src/components/gocardless/GoCardlessLink.tsx
+++ b/packages/desktop-client/src/components/gocardless/GoCardlessLink.tsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import { Trans } from 'react-i18next';
 
 import { Modal, ModalHeader } from '../common/Modal';
 import { Paragraph } from '../common/Paragraph';
@@ -10,10 +11,14 @@ export function GoCardlessLink() {
     <Modal name="gocardless-link" isDismissable={false}>
       <ModalHeader title="Account sync" />
       <View style={{ maxWidth: 500 }}>
-        <Paragraph>Please wait...</Paragraph>
         <Paragraph>
-          The window should close automatically. If nothing happened you can
-          close this window or tab.
+          <Trans>Please wait...</Trans>
+        </Paragraph>
+        <Paragraph>
+          <Trans>
+            The window should close automatically. If nothing happened you can
+            close this window or tab.
+          </Trans>
         </Paragraph>
       </View>
     </Modal>
diff --git a/packages/desktop-client/src/components/manager/BudgetList.tsx b/packages/desktop-client/src/components/manager/BudgetList.tsx
index d9e7a3fd1a9d3d739a02612bc61d191c18985d4c..c12700fa9a4894420a8ea6e63cb23875b18b36a3 100644
--- a/packages/desktop-client/src/components/manager/BudgetList.tsx
+++ b/packages/desktop-client/src/components/manager/BudgetList.tsx
@@ -1,4 +1,5 @@
 import React, { useState, useRef, type CSSProperties } from 'react';
+import { Trans, useTranslation } from 'react-i18next';
 import { useDispatch, useSelector } from 'react-redux';
 
 import {
@@ -38,19 +39,19 @@ import { Popover } from '../common/Popover';
 import { Text } from '../common/Text';
 import { View } from '../common/View';
 
-function getFileDescription(file: File) {
+function getFileDescription(file: File, t: (key: string) => string) {
   if (file.state === 'unknown') {
-    return (
+    return t(
       'This is a cloud-based file but its state is unknown because you ' +
-      'are offline.'
+        'are offline.',
     );
   }
 
   if (file.encryptKeyId) {
     if (file.hasKey) {
-      return 'This file is encrypted and you have key to access it.';
+      return t('This file is encrypted and you have key to access it.');
     }
-    return 'This file is encrypted and you do not have the key for it.';
+    return t('This file is encrypted and you do not have the key for it.');
   }
 
   return null;
@@ -74,7 +75,9 @@ function FileMenu({
     }
   }
 
-  const items = [{ name: 'delete', text: 'Delete' }];
+  const { t } = useTranslation();
+
+  const items = [{ name: 'delete', text: t('Delete') }];
   const { isNarrowWidth } = useResponsive();
 
   const defaultMenuItemStyle = isNarrowWidth
@@ -124,6 +127,8 @@ function FileMenuButton({ onDelete }: { onDelete: () => void }) {
 }
 
 function FileState({ file }: { file: File }) {
+  const { t } = useTranslation();
+
   let Icon;
   let status;
   let color;
@@ -131,21 +136,21 @@ function FileState({ file }: { file: File }) {
   switch (file.state) {
     case 'unknown':
       Icon = SvgCloudUnknown;
-      status = 'Network unavailable';
+      status = t('Network unavailable');
       color = theme.buttonNormalDisabledText;
       break;
     case 'remote':
       Icon = SvgCloudDownload;
-      status = 'Available for download';
+      status = t('Available for download');
       break;
     case 'local':
     case 'broken':
       Icon = SvgFileDouble;
-      status = 'Local';
+      status = t('Local');
       break;
     default:
       Icon = SvgCloudCheck;
-      status = 'Syncing';
+      status = t('Syncing');
       break;
   }
 
@@ -182,6 +187,8 @@ function FileItem({
   onSelect: (file: File) => void;
   onDelete: (file: File) => void;
 }) {
+  const { t } = useTranslation();
+
   const selecting = useRef(false);
 
   async function _onSelect(file: File) {
@@ -197,7 +204,7 @@ function FileItem({
   return (
     <View
       onClick={() => _onSelect(file)}
-      title={getFileDescription(file) || ''}
+      title={getFileDescription(file, t) || ''}
       style={{
         flexDirection: 'row',
         justifyContent: 'space-between',
@@ -277,7 +284,7 @@ function BudgetFiles({
             color: theme.pageTextSubdued,
           }}
         >
-          No budget files
+          <Trans>No budget files</Trans>
         </Text>
       ) : (
         files.map(file => (
@@ -343,7 +350,7 @@ function BudgetListHeader({
           ...styles.veryLargeText,
         }}
       >
-        Files
+        <Trans>Files</Trans>
       </Text>
       {!quickSwitchMode && <RefreshButton onRefresh={onRefresh} />}
     </View>
@@ -452,7 +459,7 @@ export function BudgetList({ showHeader = true, quickSwitchMode = false }) {
               dispatch(pushModal('import'));
             }}
           >
-            Import file
+            <Trans>Import file</Trans>
           </Button>
 
           <Button
@@ -463,7 +470,7 @@ export function BudgetList({ showHeader = true, quickSwitchMode = false }) {
               marginLeft: 10,
             }}
           >
-            Create new file
+            <Trans>Create new file</Trans>
           </Button>
 
           {isNonProductionEnvironment() && (
@@ -475,7 +482,7 @@ export function BudgetList({ showHeader = true, quickSwitchMode = false }) {
                 marginLeft: 10,
               }}
             >
-              Create test file
+              <Trans>Create test file</Trans>
             </Button>
           )}
         </View>
diff --git a/packages/desktop-client/src/components/modals/GoCardlessExternalMsgModal.tsx b/packages/desktop-client/src/components/modals/GoCardlessExternalMsgModal.tsx
index 51b2c4af16ff1eacc7941ca19a19d174d895540f..37d4913f224e7e04ec6da470cfeea07ae441dba2 100644
--- a/packages/desktop-client/src/components/modals/GoCardlessExternalMsgModal.tsx
+++ b/packages/desktop-client/src/components/modals/GoCardlessExternalMsgModal.tsx
@@ -1,5 +1,6 @@
 // @ts-strict-ignore
 import React, { useEffect, useState, useRef } from 'react';
+import { Trans, useTranslation } from 'react-i18next';
 import { useDispatch } from 'react-redux';
 
 import { pushModal } from 'loot-core/src/client/actions/modals';
@@ -61,12 +62,12 @@ function useAvailableBanks(country: string) {
   };
 }
 
-function renderError(error: 'unknown' | 'timeout') {
+function renderError(error: 'unknown' | 'timeout', t: (key: string) => string) {
   return (
     <Error style={{ alignSelf: 'center' }}>
       {error === 'timeout'
-        ? 'Timed out. Please try again.'
-        : 'An error occurred while linking your account, sorry!'}
+        ? t('Timed out. Please try again.')
+        : t('An error occurred while linking your account, sorry!')}
     </Error>
   );
 }
@@ -84,6 +85,8 @@ export function GoCardlessExternalMsgModal({
   onSuccess,
   onClose,
 }: GoCardlessExternalMsgProps) {
+  const { t } = useTranslation();
+
   const dispatch = useDispatch();
 
   const [waiting, setWaiting] = useState<string | null>(null);
@@ -140,37 +143,45 @@ export function GoCardlessExternalMsgModal({
     return (
       <View style={{ gap: 10 }}>
         <FormField>
-          <FormLabel title="Choose your country:" htmlFor="country-field" />
+          <FormLabel
+            title={t('Choose your country:')}
+            htmlFor="country-field"
+          />
           <Autocomplete
             strict
             highlightFirst
             suggestions={COUNTRY_OPTIONS}
             onSelect={setCountry}
             value={country}
-            inputProps={{ id: 'country-field', placeholder: '(please select)' }}
+            inputProps={{
+              id: 'country-field',
+              placeholder: t('(please select)'),
+            }}
           />
         </FormField>
 
         {isBankOptionError ? (
           <Error>
-            Failed loading available banks: GoCardless access credentials might
-            be misconfigured. Please{' '}
-            <Link
-              variant="text"
-              onClick={onGoCardlessInit}
-              style={{ color: theme.formLabelText, display: 'inline' }}
-            >
-              set them up
-            </Link>{' '}
-            again.
+            <Trans>
+              Failed loading available banks: GoCardless access credentials
+              might be misconfigured. Please{' '}
+              <Link
+                variant="text"
+                onClick={onGoCardlessInit}
+                style={{ color: theme.formLabelText, display: 'inline' }}
+              >
+                set them up
+              </Link>{' '}
+              again.
+            </Trans>
           </Error>
         ) : (
           country &&
           (isBankOptionsLoading ? (
-            'Loading banks...'
+            t('Loading banks...')
           ) : (
             <FormField>
-              <FormLabel title="Choose your bank:" htmlFor="bank-field" />
+              <FormLabel title={t('Choose your bank:')} htmlFor="bank-field" />
               <Autocomplete
                 focused
                 strict
@@ -180,7 +191,7 @@ export function GoCardlessExternalMsgModal({
                 value={institutionId}
                 inputProps={{
                   id: 'bank-field',
-                  placeholder: '(please select)',
+                  placeholder: t('(please select)'),
                 }}
               />
             </FormField>
@@ -188,18 +199,20 @@ export function GoCardlessExternalMsgModal({
         )}
 
         <Warning>
-          By enabling bank-sync, you will be granting GoCardless (a third party
-          service) read-only access to your entire account’s transaction
-          history. This service is not affiliated with Actual in any way. Make
-          sure you’ve read and understand GoCardless’s{' '}
-          <Link
-            variant="external"
-            to="https://gocardless.com/privacy/"
-            linkColor="purple"
-          >
-            Privacy Policy
-          </Link>{' '}
-          before proceeding.
+          <Trans>
+            By enabling bank-sync, you will be granting GoCardless (a third
+            party service) read-only access to your entire account’s transaction
+            history. This service is not affiliated with Actual in any way. Make
+            sure you’ve read and understand GoCardless’s{' '}
+            <Link
+              variant="external"
+              to="https://gocardless.com/privacy/"
+              linkColor="purple"
+            >
+              Privacy Policy
+            </Link>{' '}
+            before proceeding.
+          </Trans>
         </Warning>
 
         <View style={{ flexDirection: 'row', gap: 10, alignItems: 'center' }}>
@@ -215,7 +228,7 @@ export function GoCardlessExternalMsgModal({
             onPress={onJump}
             isDisabled={!institutionId || !country}
           >
-            Link bank in browser &rarr;
+            <Trans>Link bank in browser &rarr;</Trans>
           </Button>
         </View>
       </View>
@@ -231,17 +244,19 @@ export function GoCardlessExternalMsgModal({
       {({ state: { close } }) => (
         <>
           <ModalHeader
-            title="Link Your Bank"
+            title={t('Link Your Bank')}
             rightContent={<ModalCloseButton onPress={close} />}
           />
           <View>
             <Paragraph style={{ fontSize: 15 }}>
-              To link your bank account, you will be redirected to a new page
-              where GoCardless will ask to connect to your bank. GoCardless will
-              not be able to withdraw funds from your accounts.
+              <Trans>
+                To link your bank account, you will be redirected to a new page
+                where GoCardless will ask to connect to your bank. GoCardless
+                will not be able to withdraw funds from your accounts.
+              </Trans>
             </Paragraph>
 
-            {error && renderError(error)}
+            {error && renderError(error, t)}
 
             {waiting || isConfigurationLoading ? (
               <View style={{ alignItems: 'center', marginTop: 15 }}>
@@ -251,11 +266,11 @@ export function GoCardlessExternalMsgModal({
                 />
                 <View style={{ marginTop: 10, color: theme.pageText }}>
                   {isConfigurationLoading
-                    ? 'Checking GoCardless configuration..'
+                    ? t('Checking GoCardless configuration..')
                     : waiting === 'browser'
-                      ? 'Waiting on GoCardless...'
+                      ? t('Waiting on GoCardless...')
                       : waiting === 'accounts'
-                        ? 'Loading accounts...'
+                        ? t('Loading accounts...')
                         : null}
                 </View>
 
@@ -265,7 +280,9 @@ export function GoCardlessExternalMsgModal({
                     onClick={onJump}
                     style={{ marginTop: 10 }}
                   >
-                    (Account linking not opening in a new tab? Click here)
+                    <Trans>
+                      (Account linking not opening in a new tab? Click here)
+                    </Trans>
                   </Link>
                 )}
               </View>
@@ -281,17 +298,19 @@ export function GoCardlessExternalMsgModal({
                 }}
                 onPress={onContinue}
               >
-                Success! Click to continue &rarr;
+                <Trans>Success! Click to continue &rarr;</Trans>
               </Button>
             ) : isConfigured || isGoCardlessSetupComplete ? (
               renderLinkButton()
             ) : (
               <>
                 <Paragraph style={{ color: theme.errorText }}>
-                  GoCardless integration has not yet been configured.
+                  <Trans>
+                    GoCardless integration has not yet been configured.
+                  </Trans>
                 </Paragraph>
                 <Button variant="primary" onPress={onGoCardlessInit}>
-                  Configure GoCardless integration
+                  <Trans>Configure GoCardless integration</Trans>
                 </Button>
               </>
             )}
diff --git a/upcoming-release-notes/3430.md b/upcoming-release-notes/3430.md
new file mode 100644
index 0000000000000000000000000000000000000000..941288195368c3645d2a970a9384fe3fc2c666c2
--- /dev/null
+++ b/upcoming-release-notes/3430.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [a-gradina]
+---
+
+Support translations for component files