Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use useTranslation hook instead of directly importing the t function #3893

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

joel-jeremy
Copy link
Contributor

@joel-jeremy joel-jeremy commented Nov 25, 2024

We should use useTranslation instead of directly import the t function because useTranslation has some functionalities that are specific to react e.g. rerendering the components when language changes

There are still some direct imports left in loot-core. We need to assess if we should translate strings at that level or we should do all translations in the desktop-client/component level.

#3329

@actual-github-bot actual-github-bot bot changed the title Use useTranslation hook instead of directly importing the t function [WIP] Use useTranslation hook instead of directly importing the t function Nov 25, 2024
Copy link

netlify bot commented Nov 25, 2024

Deploy Preview for actualbudget ready!

Name Link
🔨 Latest commit e631668
🔍 Latest deploy log https://app.netlify.com/sites/actualbudget/deploys/6744cc11b7b8660008663453
😎 Deploy Preview https://deploy-preview-3893.demo.actualbudget.org
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

github-actions bot commented Nov 25, 2024

Bundle Stats — desktop-client

Hey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle.

As this PR is updated, I'll keep you updated on how the bundle size is impacted.

Total

Files count Total bundle size % Changed
10 5.45 MB → 5.46 MB (+2.39 kB) +0.04%
Changeset
File Δ Size
src/components/ManageRulesPage.tsx 📈 +32 B (+13.73%) 233 B → 265 B
src/components/mobile/transactions/AddTransactionButton.tsx 📈 +32 B (+6.20%) 516 B → 548 B
src/components/mobile/MobileBackButton.tsx 📈 +32 B (+4.38%) 730 B → 762 B
src/components/rules/RulesHeader.tsx 📈 +30 B (+4.14%) 724 B → 754 B
src/components/accounts/AccountSyncCheck.tsx 📈 +232 B (+4.01%) 5.65 kB → 5.88 kB
src/components/modals/ManageRulesModal.tsx 📈 +30 B (+2.83%) 1.04 kB → 1.06 kB
src/components/settings/Reset.tsx 📈 +52 B (+2.26%) 2.24 kB → 2.29 kB
src/components/modals/ScheduledTransactionMenuModal.tsx 📈 +62 B (+2.25%) 2.69 kB → 2.75 kB
src/components/modals/BudgetListModal.tsx 📈 +30 B (+2.07%) 1.42 kB → 1.45 kB
src/components/modals/PayeeAutocompleteModal.tsx 📈 +32 B (+1.82%) 1.72 kB → 1.75 kB
src/components/settings/UI.tsx 📈 +30 B (+1.62%) 1.81 kB → 1.84 kB
src/components/NotesButton.tsx 📈 +32 B (+1.51%) 2.07 kB → 2.1 kB
src/components/settings/BudgetTypeSettings.tsx 📈 +30 B (+1.48%) 1.98 kB → 2.01 kB
src/components/reports/SaveReportName.tsx 📈 +34 B (+1.48%) 2.25 kB → 2.28 kB
src/components/modals/CategoryAutocompleteModal.tsx 📈 +30 B (+1.31%) 2.23 kB → 2.26 kB
src/components/settings/Themes.tsx 📈 +30 B (+1.26%) 2.32 kB → 2.35 kB
src/components/Notes.tsx 📈 +32 B (+1.25%) 2.49 kB → 2.52 kB
src/components/modals/TrackingBalanceMenuModal.tsx 📈 +32 B (+1.25%) 2.5 kB → 2.53 kB
src/components/settings/index.tsx 📈 +78 B (+1.24%) 6.13 kB → 6.21 kB
src/components/modals/EnvelopeBalanceMenuModal.tsx 📈 +32 B (+1.22%) 2.56 kB → 2.6 kB
src/components/modals/TrackingBudgetMenuModal.tsx 📈 +32 B (+1.17%) 2.68 kB → 2.71 kB
src/components/modals/EnvelopeBudgetMenuModal.tsx 📈 +32 B (+1.17%) 2.68 kB → 2.71 kB
src/components/modals/CategoryMenuModal.tsx 📈 +64 B (+1.16%) 5.37 kB → 5.43 kB
src/components/settings/Export.tsx 📈 +26 B (+1.15%) 2.2 kB → 2.22 kB
src/components/mobile/transactions/TransactionListWithBalances.jsx 📈 +62 B (+1.14%) 5.29 kB → 5.35 kB
src/components/common/Modal.tsx 📈 +96 B (+0.98%) 9.54 kB → 9.63 kB
src/components/modals/CategoryGroupMenuModal.tsx 📈 +62 B (+0.98%) 6.2 kB → 6.26 kB
src/components/mobile/accounts/Accounts.tsx 📈 +68 B (+0.90%) 7.4 kB → 7.47 kB
src/components/util/AmountInput.tsx 📈 +32 B (+0.79%) 3.93 kB → 3.96 kB
src/components/reports/reports/GetCardData.tsx 📈 +34 B (+0.79%) 4.2 kB → 4.23 kB
src/components/reports/reports/CustomReportListCards.tsx 📈 +34 B (+0.78%) 4.25 kB → 4.28 kB
src/components/Titlebar.tsx 📈 +62 B (+0.75%) 8.02 kB → 8.08 kB
src/components/settings/FixSplits.tsx 📈 +24 B (+0.74%) 3.17 kB → 3.19 kB
src/components/rules/ActionExpression.tsx 📈 +30 B (+0.73%) 4.02 kB → 4.05 kB
src/components/modals/SelectLinkedAccountsModal.jsx 📈 +50 B (+0.68%) 7.19 kB → 7.24 kB
src/components/rules/Value.tsx 📈 +32 B (+0.65%) 4.79 kB → 4.82 kB
src/components/reports/ReportTopbar.tsx 📈 +34 B (+0.59%) 5.58 kB → 5.62 kB
src/components/mobile/budget/BudgetTable.jsx 📈 +306 B (+0.56%) 53.8 kB → 54.1 kB
src/components/modals/GoCardlessInitialiseModal.tsx 📈 +20 B (+0.50%) 3.91 kB → 3.93 kB
src/components/select/RecurringSchedulePicker.tsx 📈 +80 B (+0.48%) 16.29 kB → 16.37 kB
src/components/settings/Format.tsx 📈 +22 B (+0.47%) 4.55 kB → 4.58 kB
src/components/Notifications.tsx 📈 +32 B (+0.45%) 6.94 kB → 6.97 kB
src/components/reports/CategorySelector.tsx 📈 +34 B (+0.40%) 8.38 kB → 8.42 kB
src/components/modals/MergeUnusedPayeesModal.tsx 📈 +26 B (+0.39%) 6.52 kB → 6.55 kB
src/components/transactions/SimpleTransactionsTable.tsx 📈 +20 B (+0.32%) 6.19 kB → 6.21 kB
src/components/modals/EditFieldModal.tsx 📈 +22 B (+0.29%) 7.47 kB → 7.49 kB
src/components/modals/CreateLocalAccountModal.tsx 📈 +16 B (+0.22%) 7.15 kB → 7.17 kB
src/components/modals/FixEncryptionKeyModal.tsx 📈 +12 B (+0.20%) 5.8 kB → 5.81 kB
src/components/reports/ReportSidebar.tsx 📈 +34 B (+0.19%) 17.6 kB → 17.63 kB
src/components/mobile/transactions/TransactionList.jsx 📈 +28 B (+0.18%) 15.5 kB → 15.52 kB
src/components/modals/EditRuleModal.jsx 📈 +52 B (+0.13%) 39.65 kB → 39.7 kB
src/components/mobile/transactions/TransactionEdit.jsx 📈 +36 B (+0.10%) 33.88 kB → 33.91 kB
src/components/modals/CreateEncryptionKeyModal.tsx 📈 +6 B (+0.07%) 8.44 kB → 8.44 kB
src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx 📈 +4 B (+0.01%) 30.12 kB → 30.13 kB
View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

Asset File Size % Changed
static/js/index.js 3.44 MB → 3.44 MB (+1.83 kB) +0.05%
static/js/narrow.js 82.93 kB → 83.29 kB (+374 B) +0.44%
static/js/ReportRouter.js 1.52 MB → 1.52 MB (+204 B) +0.01%

Smaller

No assets were smaller

Unchanged

Asset File Size % Changed
static/js/workbox-window.prod.es5.js 5.69 kB 0%
static/js/indexeddb-main-thread-worker-e59fee74.js 13.5 kB 0%
static/js/resize-observer.js 18.37 kB 0%
static/js/BackgroundImage.js 122.29 kB 0%
static/js/useAccountPreviewTransactions.js 1.68 kB 0%
static/js/AppliedFilters.js 21.32 kB 0%
static/js/wide.js 241.19 kB 0%

Copy link
Contributor

github-actions bot commented Nov 25, 2024

Bundle Stats — loot-core

Hey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle.

As this PR is updated, I'll keep you updated on how the bundle size is impacted.

Total

Files count Total bundle size % Changed
1 1.32 MB 0%

Changeset

No files were changed

View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

No assets were bigger

Smaller

No assets were smaller

Unchanged

Asset File Size % Changed
kcab.worker.js 1.32 MB 0%

@joel-jeremy joel-jeremy changed the title [WIP] Use useTranslation hook instead of directly importing the t function Use useTranslation hook instead of directly importing the t function Nov 25, 2024
Copy link
Contributor

coderabbitai bot commented Nov 25, 2024

Walkthrough

This pull request introduces a comprehensive update across multiple components in the desktop client, primarily focusing on enhancing internationalization support by integrating the useTranslation hook from the react-i18next library. The changes involve replacing direct imports of the t function from i18next with the hook-based approach, allowing for more modular and maintainable translation handling. Components such as ManageRulesPage, Notes, Notifications, and various modal components have been updated to utilize the t function directly from the useTranslation hook for translating user-facing strings. This shift not only improves localization capabilities but also maintains the existing logic and structure of the components. The overall functionality, including props and state management, remains intact, ensuring that the user experience is preserved while enhancing the adaptability of the application to different languages.

Possibly related PRs

Suggested labels

:sparkles: Merged

Suggested reviewers

  • MikesGlitch

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/desktop-client/src/components/ManageRulesPage.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-eslint-plugin".

(The package "eslint-plugin-eslint-plugin" was not found when loaded as a Node module from the directory "/packages/eslint-plugin-actual".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-eslint-plugin@latest --save-dev

The plugin "eslint-plugin-eslint-plugin" was referenced from the config file in "packages/eslint-plugin-actual/.eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (70)
packages/desktop-client/src/components/mobile/MobileBackButton.tsx (1)

17-17: Consider memoization for performance optimization

While the current implementation is correct, consider using useMemo for the translation function if this component re-renders frequently or is used in a performance-critical part of the application.

- const { t } = useTranslation();
+ const { t } = useMemo(() => useTranslation(), []);
packages/desktop-client/src/components/modals/ManageRulesModal.tsx (1)

Translation keys need to be updated for consistency

Based on the search results, I found that:

  1. The translation key 'manage-rules' is used consistently in the codebase for modal naming
  2. However, 'Rules' is used directly without proper translation key formatting (should be kebab-case like other keys)

Locations that need attention:

  • packages/desktop-client/src/components/ManageRulesPage.tsx: Change t('Rules') to t('rules')
  • packages/desktop-client/src/components/modals/ManageRulesModal.tsx: Change t('Rules') to t('rules')
  • packages/desktop-client/src/components/sidebar/PrimaryButtons.tsx: Change title={t('Rules')} to title={t('rules')}
🔗 Analysis chain

Line range hint 29-29: Verify translation key consistency

The translation keys 'manage-rules' and 'Rules' are used. Let's ensure these keys:

  1. Exist in the translation files
  2. Follow consistent casing conventions across the codebase

Also applies to: 33-33

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check translation keys existence and consistency

# Search for translation files
echo "Searching for translation files..."
fd -e json -e yaml "translation" -x cat {} \; | grep -E "(manage-rules|Rules)"

# Check for inconsistent casing in translation keys
echo "Checking translation key usage patterns..."
rg "t\(['\"].*rules.*['\"]" --type ts --type tsx

Length of output: 338


Script:

#!/bin/bash
# Let's try a different approach to find translation files and usages

# First, let's find all potential translation-related files
echo "=== Looking for translation-related files ==="
fd "translation|locale|i18n" --type file

# Then, let's search for rules-related translations in TypeScript/JavaScript files
echo -e "\n=== Searching for translation patterns ==="
rg "t\(['\"].*rules.*['\"]" -t ts -t js

# Let's also check for the specific keys we're interested in
echo -e "\n=== Searching for specific translation keys ==="
rg "(manage-rules|Rules)" -t ts -t js -t json

Length of output: 27828

packages/desktop-client/src/components/modals/BudgetListModal.tsx (1)

Line range hint 11-44: Consider memoization for performance optimization

Since this modal might be rendered frequently during budget switching operations, consider wrapping the component with React.memo to prevent unnecessary re-renders when parent components update. The useTranslation hook will still trigger re-renders when the language changes.

-export function BudgetListModal() {
+export const BudgetListModal = React.memo(function BudgetListModal() {
   const { t } = useTranslation();
   // ... rest of the component
-}
+});
packages/desktop-client/src/components/settings/BudgetTypeSettings.tsx (2)

Line range hint 24-28: Consider using translation for button text

The button text could benefit from using translations for consistency with the rest of the internationalization efforts.

Consider this improvement:

 <Button onPress={onSwitchType}>
-  Switch to {budgetType === 'report' ? 'envelope' : 'tracking'}{' '}
-  budgeting
+  {t('Switch to {{type}} budgeting', {
+    type: budgetType === 'report' ? t('envelope') : t('tracking')
+  })}
 </Button>

Line range hint 31-57: Consider translating all user-facing strings

While "Learn more..." links are translated, the main descriptive text about budget types is not. For consistency and complete internationalization support, consider translating all user-facing strings.

Here's how you could improve it:

 <Text>
-  <strong>Envelope budgeting</strong> (recommended) digitally mimics
-  physical envelope budgeting system by allocating funds into virtual
-  envelopes for different expenses. It helps track spending and ensure you
-  don't overspend in any category.{' '}
+  {t('envelope_budgeting_description', {
+    defaultValue: '<strong>Envelope budgeting</strong> (recommended) digitally mimics physical envelope budgeting system by allocating funds into virtual envelopes for different expenses. It helps track spending and ensure you don\'t overspend in any category.',
+    interpolation: { escapeValue: false }
+  })}{' '}
   <Link
     variant="external"
     to="https://actualbudget.org/docs/getting-started/envelope-budgeting"
     linkColor="purple"
   >
     {t('Learn more…')}
   </Link>
 </Text>

Apply similar changes to the tracking budgeting description as well.

packages/desktop-client/src/components/settings/Export.tsx (1)

Line range hint 63-69: Consider translating all user-facing strings

There are some hardcoded strings that should be translated for consistency:

  • The "Export" text in the strong tag
  • The technical explanation about db.sqlite and metadata.json files

Consider updating the text block like this:

- <Text>
-   <strong>Export</strong> your data as a zip file containing{' '}
-   <code>db.sqlite</code> and <code>metadata.json</code> files. It can be
-   imported into another Actual instance by closing an open file (if any),
-   then clicking the "Import file" button, then choosing "Actual."
- </Text>
+ <Text>
+   <strong>{t('Export')}</strong>{' '}
+   {t('your data as a zip file containing {{sqlite}} and {{metadata}} files. It can be imported into another Actual instance by closing an open file (if any), then clicking the "Import file" button, then choosing "Actual."', {
+     sqlite: <code>db.sqlite</code>,
+     metadata: <code>metadata.json</code>,
+   })}
+ </Text>
packages/desktop-client/src/components/settings/UI.tsx (1)

Line range hint 53-93: Consider adding type safety for translations

To improve maintainability and catch missing translations at compile time, consider implementing type safety for translation keys. This could be achieved using:

  1. TypeScript's string literal types for translation keys
  2. Auto-generated types from your translation files
  3. A type-safe translation key management solution

This would help prevent typos and make refactoring easier.

packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx (3)

26-26: LGTM: Proper useTranslation hook implementation

The hook is correctly implemented at the component's top level, which will enable automatic re-rendering when the language changes - an improvement over the direct import approach.

This change improves the component's reactivity to language changes, which is particularly important for a modal component that might be open during language switches.


Line range hint 64-64: Consider translating additional UI elements

While the 'Payee' title is now properly translated, consider also translating other user-facing strings that might be passed through props, such as aria-labels or button texts.

For example, you might want to ensure that texts passed to showManagePayees and showMakeTransfer buttons (if any) are also translated consistently.


Direct imports of t from i18next should be migrated to useTranslation hook

Found 6 files still using direct imports of t from i18next that should be updated to use the useTranslation hook for consistency:

  • packages/desktop-client/src/components/util/accountValidation.ts
  • packages/desktop-client/src/components/schedules/ScheduleDetails.jsx
  • packages/desktop-client/src/components/reports/ReportOptions.ts
  • packages/desktop-client/src/components/reports/disabledList.ts
  • packages/desktop-client/src/components/budget/util.ts
  • packages/desktop-client/src/components/accounts/Account.tsx
🔗 Analysis chain

Line range hint 1-85: Verify consistent translation pattern across related components

The implementation looks good overall. Let's verify that this translation pattern is consistently applied across related components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining direct imports of 't' from i18next
rg "import.*\{.*t.*\}.*from 'i18next'" packages/desktop-client/src/

# Check for consistent usage of useTranslation in modal components
rg "useTranslation.*from 'react-i18next'" packages/desktop-client/src/components/modals/

Length of output: 6979

packages/desktop-client/src/components/settings/Reset.tsx (1)

42-42: Consider consolidating conditional translations

The current implementation splits the disabled state message into separate translation keys, which might cause issues for languages with different word orders. Consider consolidating the translation into a single key.

-        <Text>
-          <strong>{t('Reset sync')}</strong>
-          {t(' is only available when syncing is')}
-        </Text>
+        <Text>
+          {t('Reset sync is only available when syncing is enabled')}
+        </Text>

Also applies to: 74-78

packages/desktop-client/src/components/settings/Themes.tsx (1)

Line range hint 94-97: Consider combining the translation strings for better localization

The current implementation splits the text into two parts with a hardcoded space. This could cause issues in languages with different word orders or formatting requirements.

Consider combining the strings into a single translation key:

-      <Text>
-        <strong>{t('Themes')}</strong>
-        {t(' change the user interface colors.')}
-      </Text>
+      <Text>
+        {t('themes.description', {
+          themes: text => <strong>{text}</strong>
+        })}
+      </Text>

Add to your translation file:

{
  "themes.description": "{{themes, themes}} change the user interface colors"
}

This approach:

  • Gives translators more context
  • Allows for proper word order in different languages
  • Eliminates hardcoded spacing issues
packages/desktop-client/src/components/modals/CategoryAutocompleteModal.tsx (1)

Line range hint 52-52: Consider extracting duplicate translation key

The translation key 'Category' is used in two places. While the current implementation is functional, consider extracting it to a constant for better maintainability:

+ const CATEGORY_LABEL = 'Category';

  return (
    <Modal>
      {({ state: { close } }) => (
        <>
          {isNarrowWidth && (
            <ModalHeader
              title={
                <ModalTitle
-                 title={t('Category')}
+                 title={t(CATEGORY_LABEL)}
                  getStyle={() => ({ color: theme.menuAutoCompleteText })}
                />
              }
          />
          )}
          <View>
            {!isNarrowWidth && (
              <SectionLabel
-               title={t('Category')}
+               title={t(CATEGORY_LABEL)}
                style={{
                  alignSelf: 'center',

Also applies to: 71-71

packages/desktop-client/src/components/Notes.tsx (1)

Line range hint 119-127: Consider adding ARIA label for better accessibility.

While the translation implementation is correct, consider adding an aria-label to improve accessibility for screen readers, as placeholders might not always be read.

    <textarea
      ref={textAreaRef}
      className={css({
        border: '1px solid ' + theme.buttonNormalBorder,
        padding: 7,
        ...(!isNarrowWidth && { minWidth: 350, minHeight: 120 }),
        outline: 'none',
        backgroundColor: theme.tableBackground,
        color: theme.tableText,
        ...getStyle?.(editable),
      })}
      value={notes || ''}
      onChange={e => onChange?.(e.target.value)}
      onBlur={e => onBlur?.(e.target.value)}
      placeholder={t('Notes (markdown supported)')}
+     aria-label={t('Notes input field with markdown support')}
    />
packages/desktop-client/src/components/modals/ScheduledTransactionMenuModal.tsx (1)

Missing translation key and translation file

The translation key 'Scheduled date' is not found because the translation file en.json is missing from the configured location packages/desktop-client/src/locale/. Based on the i18n configuration and implementation:

  • The translation file should be at packages/desktop-client/src/locale/en.json
  • The configuration is set up to extract translations from source files
  • The key separator is disabled, meaning full phrases are used as keys
🔗 Analysis chain

Line range hint 71-71: Verify translation key existence.

The translation key 'Scheduled date' is used for user-facing content.


Let me verify if there are any translation files in the repository first, and then check for similar translation keys to ensure we're searching correctly.


Let's check the i18n configuration and implementation since we found the relevant files.


Let's check for the actual translation file in the location specified in the configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the translation key exists in translation files
# Look for the translation key in JSON/YAML files that might contain translations
rg -g '*.{json,yaml,yml}' '"Scheduled date"' || echo "Translation key not found"

Length of output: 107


Script:

#!/bin/bash
# First, let's find translation files
echo "=== Looking for translation files ==="
fd -e json -e yaml -e yml | grep -i 'translation\|locale\|lang'

echo -e "\n=== Looking for i18n configuration files ==="
fd -e js -e ts -e json | grep -i 'i18n'

echo -e "\n=== Looking for similar translation keys about scheduling ==="
rg -g '*.{json,yaml,yml}' -i 'schedul' || echo "No scheduling-related translations found"

Length of output: 958


Script:

#!/bin/bash
# Check i18n configuration and implementation
echo "=== Checking i18n configuration ==="
cat packages/desktop-client/i18next-parser.config.js

echo -e "\n=== Checking i18n implementation ==="
cat packages/desktop-client/src/i18n.ts

echo -e "\n=== Looking for translation files in common locations ==="
fd -e json -e yaml -e yml . packages/desktop-client/src/locales packages/desktop-client/public/locales 2>/dev/null || echo "No translation files found in common locations"

Length of output: 1802


Script:

#!/bin/bash
# Check for translation file in the configured location
echo "=== Checking for en.json in src/locale ==="
cat packages/desktop-client/src/locale/en.json 2>/dev/null || echo "Translation file not found"

echo -e "\n=== Looking for any json files in src/locale ==="
fd -e json . packages/desktop-client/src/locale/ 2>/dev/null || echo "No JSON files found in locale directory"

Length of output: 459

packages/desktop-client/src/components/modals/TrackingBudgetMenuModal.tsx (1)

Line range hint 89-89: Consider translating all user-facing strings.

While "Budgeted" is now translated, other potential user-facing strings in the component might also need translation for consistency.

Consider adding translations for the modal title and potentially other text:

<ModalHeader
-  title={<ModalTitle title={category.name} shrinkOnOverflow />}
+  title={<ModalTitle title={t('category.name', { name: category.name })} shrinkOnOverflow />}
  rightContent={<ModalCloseButton onPress={close} />}
/>
packages/desktop-client/src/components/settings/FixSplits.tsx (1)

Line range hint 83-108: Consider improving translation key handling and HTML content

  1. Instead of using string literals directly as translation keys, consider using structured keys (e.g., settings.fixSplits.button, settings.fixSplits.description). This makes maintenance easier and provides better organization of translations.

  2. HTML markup within translation strings (like <strong> and list items) could make translations harder to maintain. Consider extracting the markup to the JSX level.

Example refactor:

- <Text>
-   <strong>{t('Repair split transactions')}</strong>
-   {t(
-     ' if you are experiencing bugs relating to split transactions and the "Reset budget cache" button above does not help, this tool may fix them. Some examples of bugs include seeing blank payees on splits or incorrect account balances. This tool does two things:',
-   )}
- </Text>
+ <Text>
+   <strong>{t('settings.fixSplits.title')}</strong>
+   {' '}
+   {t('settings.fixSplits.description')}
+ </Text>
packages/desktop-client/src/components/rules/ActionExpression.tsx (2)

Line range hint 70-82: Consider improving translation key format

While the useTranslation hook is correctly implemented, the translation strings contain trailing spaces ("to " and "template "). Consider moving space handling to the translation system or component layout.

-      <Text>{t('to ')}</Text>
+      <Text>{t('to')}</Text>{' '}
-          <Text>{t('template ')}</Text>
+          <Text>{t('template')}</Text>{' '}

Line range hint 89-143: Consider internationalizing remaining components

For consistency, consider applying the same internationalization approach to other action expression components. Text from friendlyOp() and ALLOCATION_METHODS should also be internationalized.

Example implementation for SetSplitAmountActionExpression:

 function SetSplitAmountActionExpression({
   op,
   value,
   options,
 }: SetSplitAmountRuleActionEntity) {
+  const { t } = useTranslation();
   const method = options?.method;
   if (!method) {
     return null;
   }
 
   return (
     <>
-      <Text>{friendlyOp(op)}</Text>{' '}
+      <Text>{t(friendlyOp(op))}</Text>{' '}
-      <Text style={valueStyle}>{ALLOCATION_METHODS[method]}</Text>
+      <Text style={valueStyle}>{t(ALLOCATION_METHODS[method])}</Text>
       {method !== 'remainder' && ': '}
       // ... rest of the component
     </>
   );
 }
packages/desktop-client/src/components/modals/GoCardlessInitialiseModal.tsx (3)

Line range hint 30-33: Consider implementing stronger input validation

The current state management for sensitive credentials could benefit from additional validation:

  • Length requirements for secrets
  • Format validation
  • Trimming whitespace
 const [secretId, setSecretId] = useState('');
 const [secretKey, setSecretKey] = useState('');
+const validateSecrets = (id: string, key: string) => {
+  const trimmedId = id.trim();
+  const trimmedKey = key.trim();
+  return {
+    isValid: trimmedId.length >= 8 && trimmedKey.length >= 8,
+    trimmedId,
+    trimmedKey
+  };
+};

Line range hint 35-52: Add error handling for network requests

The submission logic should handle potential network failures and API errors.

 const onSubmit = async (close: () => void) => {
   if (!secretId || !secretKey) {
     setIsValid(false);
     return;
   }
 
   setIsLoading(true);
+  try {
     await Promise.all([
       send('secret-set', {
         name: 'gocardless_secretId',
         value: secretId,
       }),
       send('secret-set', {
         name: 'gocardless_secretKey',
         value: secretKey,
       }),
     ]);
 
     onSuccess();
-    setIsLoading(false);
     close();
+  } catch (error) {
+    setIsValid(false);
+    // Consider adding an error state to display API errors
+  } finally {
+    setIsLoading(false);
+  }
 };

Line range hint 89-117: Enhance form accessibility

While the form implements basic accessibility with labels and IDs, consider adding:

  • aria-required attributes
  • Error message association with inputs
  • Loading state announcement
 <Input
   id="secret-id-field"
   type="password"
   value={secretId}
+  aria-required="true"
+  aria-invalid={!isValid}
+  aria-describedby="error-message"
   onChangeValue={value => {
     setSecretId(value);
     setIsValid(true);
   }}
 />

 {!isValid && (
-  <Error>
+  <Error id="error-message" role="alert">
     {t(
       'It is required to provide both the secret id and secret key.',
     )}
   </Error>
 )}
packages/desktop-client/src/components/settings/Format.tsx (1)

Line range hint 24-44: Consider extracting and translating static arrays

Consider moving the daysOfWeek and dateFormats arrays to a separate constants file and making their labels translatable. This would improve maintainability and ensure consistent internationalization.

Example implementation:

// constants/dateFormats.ts
export const daysOfWeek = (t: TFunction) => [
  { value: '0', label: t('Sunday') },
  { value: '1', label: t('Monday') },
  // ...
];

export const dateFormats = (t: TFunction) => [
  { value: 'MM/dd/yyyy', label: t('MM/DD/YYYY') },
  // ...
];
packages/desktop-client/src/components/util/AmountInput.tsx (1)

158-158: Consider using a more specific translation key

While the implementation is correct, using a generic translation key like 'and' could lead to maintenance issues or unintended translations. Consider using a more specific, namespaced key that describes its context.

- {t('and')}
+ {t('amount_input.between_connector')}

Also applies to: 171-171

packages/desktop-client/src/components/rules/Value.tsx (2)

1-1: Consider improving TypeScript implementation

The file has several TypeScript-related improvements that could be made:

  1. The file starts with @ts-strict-ignore
  2. There are multiple @ts-expect-error comments
  3. The describe prop type has been improved but the implementation still has a type error

Consider addressing these TypeScript issues in a follow-up PR to improve type safety.

Would you like me to help create a GitHub issue to track these TypeScript improvements?

Also applies to: 33-37


Line range hint 156-162: Consider translating additional strings

While the "and" string is now properly translated, there are several other hardcoded strings in the component that could benefit from translation:

  • "(nothing)"
  • "(empty)"
  • "(deleted)"
  • "more items..."

This would provide a more consistent internationalization experience.

Example implementation:

- return '(nothing)';
+ return t('nothing');

- return <Text style={valueStyle}>(empty)</Text>;
+ return <Text style={valueStyle}>{t('empty')}</Text>;

- return '(deleted)';
+ return t('deleted');

- {numHidden} more items...
+ {t('more_items', { count: numHidden })}
packages/desktop-client/src/components/mobile/transactions/TransactionListWithBalances.jsx (1)

115-115: Consider using more specific translation keys

While the translation implementation is correct, consider using more specific translation keys like 'transactions.balance.cleared' and 'transactions.balance.uncleared' to maintain a clear hierarchical structure in your translations.

packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx (2)

Line range hint 47-47: Consider using structured translation keys

Instead of using a direct string as a translation key, consider using a structured key format (e.g., 'reports.custom.deleted') for better maintainability and consistency across the application.

-        {t('This custom report has been deleted.')}
+        {t('reports.custom.deleted')}

Remember to add the corresponding key-value pair in your translation files.


Missing translations for menu items and tooltip content

The following strings need to be translated:

  • Menu items: 'Rename', 'Remove' in CustomReportListCards.tsx
  • Tooltip content: "The widget is configured to use a non-existing filter value..." in CustomReportListCards.tsx

Evidence:

  1. The component uses useTranslation() hook but doesn't use the t() function for these strings
  2. Similar menu items in other components also need translation
  3. The tooltip content contains user-facing text that should be translated for consistency
🔗 Analysis chain

Line range hint 39-170: Verify translation coverage for all user-facing strings

There are several other user-facing strings in the component that might need translation, particularly in the menu items and tooltips.

Consider translating these strings as well:

  • Menu items: 'Rename', 'Remove'
  • Tooltip content for the warning icon
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential untranslated strings in the component
rg -U "text: '[^']*'" packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
rg -U "content=\"[^\"]*\"" packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx

Length of output: 452


Script:

#!/bin/bash
# Let's check if there are any other similar components using translation
ast-grep --pattern 'const { t } = useTranslation()'

# Check for any existing translations of these strings in the codebase
rg -l "('|\")(Rename|Remove|The widget is configured)('|\")" packages/desktop-client/src/locales/

Length of output: 23885


Script:

#!/bin/bash
# Let's check the actual location of translation files
fd -t f "en.json|en-US.json|translations.json" packages/desktop-client/

# Let's also check if there are any similar menu items in other components that might show the translation pattern
rg -U "text: ('|\")(?:Rename|Remove)('|\")" packages/desktop-client/

Length of output: 581

packages/desktop-client/src/components/accounts/AccountSyncCheck.tsx (2)

32-33: Remove empty default cases in switch statements.

The empty default cases don't serve any purpose and can be removed to improve code clarity.

          case 'ITEM_LOGIN_REQUIRED':
            return t(
              'Your password or something else has changed with your bank and you need to login again.',
            );
-          default:
        }
        break;

      case 'INVALID_INPUT':
        switch (code.toUpperCase()) {
          case 'INVALID_ACCESS_TOKEN':
            return t('Item is no longer authorized. You need to login again.');
-          default:
        }
        break;

Also applies to: 40-41


20-77: Consider refactoring error message handling for better maintainability.

The current implementation mixes string and JSX returns, and has a complex nested switch structure. Consider these improvements:

  1. Separate string-based messages from JSX-based messages
  2. Use a lookup object for simple string messages
  3. Add explicit error codes for better error tracking

Here's a suggested refactor:

function useErrorMessage() {
  const { t } = useTranslation();
  
  const ERROR_MESSAGES = {
    'ITEM_ERROR.NO_ACCOUNTS': t('No open accounts could be found. Did you close the account? If so, unlink the account.'),
    'ITEM_ERROR.ITEM_LOGIN_REQUIRED': t('Your password or something else has changed with your bank and you need to login again.'),
    'INVALID_INPUT.INVALID_ACCESS_TOKEN': t('Item is no longer authorized. You need to login again.'),
    'RATE_LIMIT_EXCEEDED': t('Rate limit exceeded for this item. Please try again later.'),
    'INVALID_ACCESS_TOKEN': t('Your SimpleFIN Access Token is no longer valid. Please reset and generate a new token.')
  };

  function getJSXErrorMessage(type: string, code: string) {
    if (type === 'ACCOUNT_NEEDS_ATTENTION') {
      return (
        <Trans>
          The account needs your attention at{' '}
          <Link variant="external" to="https://bridge.simplefin.org/auth/login">
            SimpleFIN
          </Link>.
        </Trans>
      );
    }
    return (
      <Trans>
        An internal error occurred. Try to login again, or get{' '}
        <Link variant="external" to="https://actualbudget.org/contact/">
          in touch
        </Link>{' '}
        for support.
      </Trans>
    );
  }

  function getErrorMessage(type: string, code: string) {
    const messageKey = code ? `${type}.${code}` : type;
    return ERROR_MESSAGES[messageKey.toUpperCase()] || getJSXErrorMessage(type, code);
  }

  return { getErrorMessage };
}
packages/desktop-client/src/components/reports/reports/GetCardData.tsx (1)

Line range hint 26-33: LGTM: Proper implementation of useTranslation hook

The translation hook is correctly implemented and follows React best practices. The error message is properly internationalized while maintaining the existing styling and layout.

Consider adding type safety to the translation key:

// Define your translation keys type
type TranslationKeys = {
  'There was a problem loading your report': string;
  // ... other keys
};

// Use it with useTranslation
const { t } = useTranslation<keyof TranslationKeys>();
packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx (1)

Line range hint 27-31: Consider handling undefined options

The default value for options has been removed, but the type definition doesn't mark it as optional. This could lead to runtime issues if options is undefined.

Consider either:

-type FixEncryptionKeyModalProps = {
-  options: FinanceModals['fix-encryption-key'];
-};
+type FixEncryptionKeyModalProps = {
+  options?: FinanceModals['fix-encryption-key'];
+};

Or restore the default value:

-export function FixEncryptionKeyModal({
-  options = {},
-}: FixEncryptionKeyModalProps) {
+export function FixEncryptionKeyModal({
+  options,
+}: FixEncryptionKeyModalProps) {
packages/desktop-client/src/components/settings/index.tsx (1)

Line range hint 114-121: Consider tracking the TODO comment

There's a low-priority TODO comment about eliminating or deciding when to show certain IDs. This could be tracked for future improvements.

Would you like me to create a GitHub issue to track this TODO item?

packages/desktop-client/src/components/reports/ReportTopbar.tsx (2)

Line range hint 74-74: Consider adding type safety for translation keys

While the translation implementation is correct, consider improving type safety by defining constants or enums for translation keys. This would help catch missing translations at compile time and make refactoring easier.

Here's an example approach:

// translations/keys.ts
export const ReportTranslationKeys = {
  dataTable: 'Data Table',
  barGraph: 'Bar Graph',
  stackedBarGraph: 'Stacked Bar Graph',
  lineGraph: 'Line Graph',
  areaGraph: 'Area Graph',
  donutGraph: 'Donut Graph',
  showLegend: 'Show Legend',
  showSummary: 'Show Summary',
  showLabels: 'Show Labels',
} as const;

// Then in component:
t(ReportTranslationKeys.dataTable)

Also applies to: 76-76, 89-93, 106-106, 119-119, 132-132, 145-145, 158-158, 171-171


Migration to useTranslation is inconsistent in reports directory

There are still a few files in the reports directory using direct t imports from 'i18next' that need to be migrated to useTranslation:

  • packages/desktop-client/src/components/reports/disabledList.ts
  • packages/desktop-client/src/components/reports/ReportOptions.ts

The rest of the reports directory has properly adopted the useTranslation hook from 'react-i18next', showing good progress in the migration.

🔗 Analysis chain

Line range hint 1-200: Verify consistent translation approach across related components

Since this is part of a larger migration to useTranslation, let's verify the consistency of the implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining direct t imports
echo "Checking for remaining direct t imports..."
rg "import.*\{ t \}.*from 'i18next'" packages/desktop-client/src/

# Check for consistent translation key usage
echo "Checking for translation key usage patterns..."
rg "t\(['\"](?:Data Table|Bar Graph|Stacked Bar Graph|Line Graph|Area Graph|Donut Graph|Show Legend|Show Summary|Show Labels)['\"]" packages/desktop-client/src/

Length of output: 1858


Script:

#!/bin/bash
# Let's check the implementation of useTranslation in the same directory
echo "Checking useTranslation implementations in reports directory..."
rg "useTranslation" packages/desktop-client/src/components/reports/

# Check for any other translation-related imports in the reports directory
echo "Checking other translation-related imports in reports directory..."
rg "import.*from ['\"].*i18next['\"]" packages/desktop-client/src/components/reports/

# Check if there are any other files that might need migration
echo "Checking for potential files needing migration..."
fd . packages/desktop-client/src/components/reports/ -e tsx -e ts -e jsx -e js --exec grep -l "t("

Length of output: 16196

packages/desktop-client/src/components/modals/CategoryMenuModal.tsx (1)

Line range hint 195-213: Consider translating menu items text.

The menu items' text strings ('Show', 'Hide', 'Delete') should be translated for consistency with the rest of the internationalization efforts.

Apply this change to the menu items:

             items={[
               !categoryGroup?.hidden && {
                 name: 'toggleVisibility',
-                text: category.hidden ? 'Show' : 'Hide',
+                text: category.hidden ? t('Show') : t('Hide'),
                 icon: category.hidden ? SvgViewShow : SvgViewHide,
                 iconSize: 16,
               },
               !categoryGroup?.hidden && Menu.line,
               {
                 name: 'delete',
-                text: 'Delete',
+                text: t('Delete'),
                 icon: SvgTrash,
                 iconSize: 15,
               },
             ]}
packages/desktop-client/src/components/modals/CreateLocalAccountModal.tsx (1)

Line range hint 147-157: Consider using translation keys with placeholders for interpolated content.

The current implementation directly interpolates components within translated strings. Consider using translation keys with placeholders for better maintainability and flexibility across different languages.

Example refactor:

- <Text>
-   {t('This cannot be changed later.')} <br /> {'\n'}
-   {t('See')}{' '}
-   <Link
-     variant="external"
-     linkColor="muted"
-     to="https://actualbudget.org/docs/accounts/#off-budget-accounts"
-   >
-     {t('Accounts Overview')}
-   </Link>{' '}
-   {t('for more information.')}
- </Text>
+ <Text>
+   {t('offbudget.warning')} <br /> {'\n'}
+   {t('offbudget.info_link', {
+     link: (
+       <Link
+         variant="external"
+         linkColor="muted"
+         to="https://actualbudget.org/docs/accounts/#off-budget-accounts"
+       >
+         {t('offbudget.docs_link')}
+       </Link>
+     ),
+   })}
+ </Text>

Translation keys would look like:

{
  "offbudget": {
    "warning": "This cannot be changed later.",
    "info_link": "See {{link}} for more information.",
    "docs_link": "Accounts Overview"
  }
}
packages/desktop-client/src/components/modals/MergeUnusedPayeesModal.tsx (2)

Line range hint 140-150: Add translation for the conditional text

While the main message is properly translated, the conditional text should also be translated for consistency:

 <Information>
   {t('Merging will remove the payee and transfer any existing rules to the new payee.')}
   {!isEditingRule && (
     <>
       {' '}
-      If checked below, a rule will be created to do this rename
-      while importing transactions.
+      {t('If checked below, a rule will be created to do this rename while importing transactions.')}
     </>
   )}
 </Information>

Line range hint 95-120: Add translations for remaining user-facing strings

Several user-facing strings in the main content area are not translated. Consider wrapping these strings with the translation function:

 {payees.length === 1 ? (
   <>
-    The payee <Text style={highlightStyle}>{payees[0].name}</Text>{' '}
-    is not used by transactions any more. Would like to merge it
-    with <Text style={highlightStyle}>{targetPayee.name}</Text>?
+    {t('The payee {{payeeName}} is not used by transactions any more. Would like to merge it with {{targetName}}?', {
+      payeeName: <Text style={highlightStyle}>{payees[0].name}</Text>,
+      targetName: <Text style={highlightStyle}>{targetPayee.name}</Text>
+    })}
   </>
 ) : (
   <>
-    The following payees are not used by transactions any more.
-    Would like to merge them with{' '}
-    <Text style={highlightStyle}>{targetPayee.name}</Text>?
+    {t('The following payees are not used by transactions any more. Would like to merge them with {{targetName}}?', {
+      targetName: <Text style={highlightStyle}>{targetPayee.name}</Text>
+    })}
   </>
 )}

Also, translate the checkbox label:

 <Text style={{ marginLeft: 3 }}>
-  Automatically rename{' '}
-  {payees.length === 1 ? 'this payee' : 'these payees'} in the
-  future
+  {t('Automatically rename {{count}} in the future', {
+    count: payees.length,
+    context: payees.length === 1 ? 'single' : 'multiple'
+  })}
 </Text>
packages/desktop-client/src/components/modals/CategoryGroupMenuModal.tsx (1)

175-175: Consider translating menu item texts

While the aria-label is properly translated, the menu item texts ("Show", "Hide", "Delete") are still hardcoded in English. Consider wrapping these strings with the translation function for consistency.

Here's how you could update the menu items:

 items={
   [
     {
       name: 'toggleVisibility',
-      text: group.hidden ? 'Show' : 'Hide',
+      text: group.hidden ? t('Show') : t('Hide'),
       icon: group.hidden ? SvgViewShow : SvgViewHide,
       iconSize: 16,
     },
     ...(!group.is_income && [
       Menu.line,
       {
         name: 'delete',
-        text: 'Delete',
+        text: t('Delete'),
         icon: SvgTrash,
         iconSize: 15,
       },
     ]),
   ].filter(i => i != null) as ComponentProps<typeof Menu>['items']
 }

Also applies to: 198-198, 227-229, 235-239

packages/desktop-client/src/components/transactions/SimpleTransactionsTable.tsx (2)

Line range hint 224-270: Consider using translation key constants

While the translation implementation is correct, consider extracting the translation keys into constants to ensure consistency and easier maintenance across the application. This would help prevent typos and make it easier to track all used translations.

Example refactor:

+ const TRANSLATION_KEYS = {
+   DATE: 'Date',
+   IMPORTED_PAYEE: 'Imported payee',
+   PAYEE: 'Payee',
+   CATEGORY: 'Category',
+   ACCOUNT: 'Account',
+   NOTES: 'Notes',
+   AMOUNT: 'Amount'
+ } as const;

  // Then in the render:
- {t('Date')}
+ {t(TRANSLATION_KEYS.DATE)}

Missing translation for 'No account' fallback text

The component has properly translated all column headers using the t() function, but there's one untranslated user-facing string:

  • The fallback text 'No account' appears twice (in both title and content) in the account field case and needs translation:
<Field key={i} width="flex" title={account?.name || t('No account')}>
  {account?.name || t('No account')}
</Field>
🔗 Analysis chain

Line range hint 1-270: Verify all user-facing strings are translated

Let's verify that no translatable strings were missed in the component.

The string 'No account' in the account field case might need translation:

- {account?.name || 'No account'}
+ {account?.name || t('No account')}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential hardcoded strings that might need translation
rg -U --type typescript --type tsx "['\"](No account|[A-Z][a-zA-Z ]+)['\"]" packages/desktop-client/src/components/transactions/SimpleTransactionsTable.tsx

Length of output: 196


Script:

#!/bin/bash
# Search for potential hardcoded strings that might need translation, using a more generic pattern
rg -U "['\"](No account|[A-Z][a-zA-Z ]+)['\"]" packages/desktop-client/src/components/transactions/SimpleTransactionsTable.tsx

Length of output: 506

packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx (4)

Line range hint 41-42: Consider consistent error state handling

The error state is set to null but rendered directly in the UI. Consider using a consistent approach with empty string to avoid potential rendering issues.

- setError(null);
+ setError('');

Line range hint 39-65: Enhance password security measures

Consider implementing:

  1. Password strength validation
  2. Secure password state management
  3. Clear password state on component unmount

Would you like me to provide an example implementation of these security enhancements?


Line range hint 89-102: Translate remaining hardcoded strings

Several strings remain untranslated:

"To enable end-to-end encryption, you need to create a key. We will generate a key based on a password and use it to encrypt from now on."
"Important:"
"if you forget this password"
"and"
"you will lose access to all your data. The data cannot be decrypted without the password."

Line range hint 146-159: Consider separating HTML markup from translations

Translation strings containing HTML markup could cause issues during translation. Consider using React components or translation keys with variables for formatting.

Example approach:

// Instead of
t('This will generate a new key for encrypting your data.') + ' ' +
<strong>{t('This requires a sync reset')}</strong>

// Consider
<Trans i18nKey="newKey.description">
  This will generate a new key for encrypting your data. 
  <strong>This requires a sync reset</strong>
</Trans>
packages/desktop-client/src/components/modals/SelectLinkedAccountsModal.jsx (1)

204-204: LGTM: Proper hook usage in child component

The useTranslation hook is correctly initialized in the TableRow component, following React hooks best practices by having each component manage its own translations rather than prop drilling the t function.

Consider memoizing the component with React.memo since it's a child component in a list:

-function TableRow({
+const TableRow = React.memo(function TableRow({
   externalAccount,
   chosenAccount,
   unlinkedAccounts,
   onSetLinkedAccount,
-}) {
+}) {
   const { t } = useTranslation();
   // ... rest of the component
-}
+});
packages/desktop-client/src/components/modals/EditFieldModal.tsx (2)

Line range hint 134-134: Consider using more specific translation keys for UI actions

While the translations work, consider using more specific translation keys for UI actions to provide better context for translators and avoid potential key conflicts. For example:

-{t('Prepend')}
+{t('notes.actions.prepend')}

-{t('Replace')}
+{t('notes.actions.replace')}

-{t('Append')}
+{t('notes.actions.append')}

This namespace structure would make it clear these are note-related actions and help translators provide more accurate translations.

Also applies to: 182-182, 230-230


Line range hint 124-234: Consider extracting button styles to reduce duplication

The button styles are duplicated across the three amendment mode buttons. Consider extracting this logic into a reusable function to improve maintainability:

const getButtonStyles = (currentMode: NoteAmendMode, buttonMode: NoteAmendMode): CSSProperties => ({
  padding: '5px 10px',
  width: '33.33%',
  backgroundColor: theme.menuBackground,
  marginRight: 5,
  fontSize: 'inherit',
  ...(currentMode === buttonMode
    ? {
        backgroundColor: theme.buttonPrimaryBackground,
        color: theme.buttonPrimaryText,
        ':hover': {
          backgroundColor: theme.buttonPrimaryBackgroundHover,
          color: theme.buttonPrimaryTextHover,
        },
      }
    : {
        backgroundColor: theme.buttonNormalBackground,
        color: theme.buttonNormalText,
        ':hover': {
          backgroundColor: theme.buttonNormalBackgroundHover,
          color: theme.buttonNormalTextHover,
        },
      }),
});

Then use it in the buttons:

<Button
  style={getButtonStyles(noteAmend, 'prepend')}
  onPress={() => {
    onChangeMode('prepend');
    noteInputRef.current?.focus();
  }}
>
  {t('notes.actions.prepend')}
</Button>
packages/desktop-client/src/components/Notifications.tsx (1)

Line range hint 234-239: Consider translating additional text content.

While the 'Close' aria-label translation is correctly implemented, there are other text elements in the component that could benefit from translation for complete internationalization coverage:

  • The title prop in the notification
  • The pre text content
  • The button.title text

Example implementation:

{title && (
  <View
    style={{
      ...styles.mediumText,
      fontWeight: 700,
      marginBottom: 10,
    }}
  >
-   {title}
+   {t(title)}
  </View>
)}
// ... and similarly for other text content
packages/desktop-client/src/components/reports/CategorySelector.tsx (1)

Line range hint 1-215: Consider translating additional UI text

While the main button labels are now properly translated, consider also translating:

  1. Category group names (if they're not coming from the database)
  2. ARIA labels or titles for accessibility
  3. Any error messages or tooltips that might be added in the future
packages/desktop-client/src/components/mobile/accounts/Accounts.tsx (2)

Line range hint 165-173: Consider using a structured translation key.

While the translation implementation is correct, using a long text string as a translation key can be harder to maintain. Consider using a structured key instead.

-        {t(
-          'For Actual to be useful, you need to add an account. You can link an account to automatically download transactions, or manage it locally yourself.',
-        )}
+        {t('accounts.empty.message')}

This makes the translations more maintainable and easier to track across the application.


Line range hint 1-319: Consider documenting the translation strategy.

The transition to useTranslation hook is well implemented. To ensure consistency across the codebase, consider:

  1. Documenting this approach in the project's contribution guidelines
  2. Creating a shared translation key structure/naming convention
  3. Setting up type checking for translation keys to catch missing translations early

This will help maintain consistency as more components are migrated to use the useTranslation hook.

packages/desktop-client/src/components/Titlebar.tsx (1)

Direct t imports found and potential translation gaps identified

Several components still use direct t imports from i18next that should be migrated to useTranslation hook:

  • packages/desktop-client/src/components/util/accountValidation.ts
  • packages/desktop-client/src/components/schedules/ScheduleDetails.jsx
  • packages/desktop-client/src/components/reports/disabledList.ts
  • packages/desktop-client/src/components/reports/ReportOptions.ts
  • packages/desktop-client/src/components/budget/util.ts
  • packages/desktop-client/src/components/accounts/Account.tsx

Additionally, multiple components contain hardcoded aria-labels that should be translated using the useTranslation hook.

🔗 Analysis chain

Line range hint 1-359: Verify consistent translation approach across related components

Let's ensure this change is consistently applied across all components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining direct imports of the t function
# that should be replaced with useTranslation hook

# Search for direct t imports
echo "Checking for direct t imports that should be replaced:"
rg "import.*\{.*t.*\}.*from.*['\"]i18next['\"]" packages/desktop-client/src/

# Search for components that might need the useTranslation hook
echo -e "\nChecking for potential missing useTranslation usage:"
rg -l "aria-label.*['\"][^'\"]+['\"]" packages/desktop-client/src/ | \
  grep -v "Titlebar.tsx" | \
  xargs -I {} echo "Potential translation needed in: {}"

Length of output: 4150

packages/desktop-client/src/components/common/Modal.tsx (2)

Line range hint 98-104: Consider using a more specific translation key

While the translation is correctly implemented, consider using a more specific key like 'common.modal.dialog_label' to better organize translations hierarchically.


17-17: Well-structured internationalization implementation

The migration to useTranslation hook is well-executed with consistent patterns across components. The implementation:

  1. Properly scopes translations to individual components
  2. Maintains good accessibility practices
  3. Follows React hooks best practices

Consider creating a shared hook (e.g., useModalTranslation) if these translation keys are reused across multiple modal-related components.

Also applies to: 57-57, 304-304, 473-473

packages/desktop-client/src/components/mobile/transactions/TransactionList.jsx (1)

Line range hint 159-159: Consider internationalizing user-facing strings in SelectedTransactionsFloatingActionBar

Several hardcoded English strings in this component could benefit from translation for consistency with the rest of the application:

  • Selection text: "{count} transactions/transaction selected"
  • Button labels: "Edit"
  • Menu items: "Account", "Payee", "Notes", etc.

Here's how you could implement this:

function SelectedTransactionsFloatingActionBar({ transactions, style }) {
+  const { t } = useTranslation();
   // ... existing code ...
   
   <Text style={styles.mediumText}>
-    {selectedTransactions.size}{' '}
-    {isMoreThanOne ? 'transactions' : 'transaction'} selected
+    {t('{{count}} {{type}} selected', {
+      count: selectedTransactions.size,
+      type: isMoreThanOne ? t('transactions') : t('transaction')
+    })}
   </Text>
   
   <Button
     variant="bare"
     ref={editMenuTriggerRef}
-    aria-label="Edit fields"
+    aria-label={t('Edit fields')}
     onPress={() => {
       setIsEditMenuOpen(true);
     }}
     {...buttonProps}
   >
-    Edit
+    {t('Edit')}
   </Button>
   
   // ... in menu items array ...
   items={[
     {
       name: 'account',
-      text: 'Account',
+      text: t('Account'),
     },
     {
       name: 'payee',
-      text: 'Payee',
+      text: t('Payee'),
     },
     // ... continue for other menu items
   ]}

Also applies to: 254-254, 279-279, 359-386

packages/desktop-client/src/components/select/RecurringSchedulePicker.tsx (3)

273-273: Consider using more descriptive translation keys for aria-labels

While the translation implementation is correct, consider using more descriptive translation keys for aria-labels to provide better context for translators. For example:

  • 'Remove recurrence' could be 'aria.label.remove_recurrence_button'
  • 'Add recurrence' could be 'aria.label.add_recurrence_button'

Also applies to: 324-324, 342-342


354-354: Improve text concatenation for better translation support

Consider avoiding string concatenation with translations. For example:

- {t('Move schedule')}{' '}
+ {t('move_schedule_weekend', { mode: state.config.weekendSolveMode })}

This allows translators to handle the full sentence structure according to their language's grammar rules.

Also applies to: 486-486, 517-517, 519-519


9-9: Consider implementing a translation key management strategy

While the migration to useTranslation is well-implemented, consider:

  1. Establishing a consistent naming convention for translation keys
  2. Creating a type-safe translation key management system
  3. Documenting translation contexts for translators

This will improve maintainability as the application's internationalization grows.

Also applies to: 273-273, 354-354, 558-558

packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (5)

Line range hint 138-166: Consider using useReducer for complex state management

The component manages numerous state variables independently. Consider using useReducer to group related state variables and their updates logically. This would make the state transitions more predictable and easier to maintain.

For example, group the file-related states, import options, and transaction states:

const initialState = {
  file: {
    filename: options.filename,
    filetype: null,
    loadingState: 'parsing',
    error: null
  },
  importOptions: {
    splitMode: false,
    flipAmount: false,
    multiplierEnabled: false,
    multiplierAmount: '',
    reconcile: true
  },
  // ... other state groups
};

Line range hint 196-308: Decompose getImportPreview for better maintainability

The getImportPreview function is handling multiple responsibilities: data transformation, validation, and preview generation. Consider breaking it down into smaller, focused functions:

function validateTransaction(trans, parseDateFormat) {
  if (!validateDate(trans.date, parseDateFormat)) {
    throw new Error(`Unable to parse date ${trans.date || '(empty)'}`);
  }
  if (!validatePayee(trans.payee_name)) {
    throw new Error(`Unable to parse payee ${trans.payee_name || '(empty')}`);
  }
  // ... other validations
}

function transformTransaction(trans, options) {
  const { splitMode, inOutMode, outValue, flipAmount, multiplierAmount } = options;
  return {
    ...trans,
    amount: parseAmountFields(trans, splitMode, inOutMode, outValue, flipAmount, multiplierAmount),
    // ... other transformations
  };
}

Line range hint 449-456: Improve multiplier validation

The current regex validation has potential issues:

  1. It allows leading zeros
  2. It doesn't prevent multiple decimal points
  3. It allows empty string which could cause issues downstream

Consider using a more robust validation:

-if (!amt || amt.match(/^\d{1,}(\.\d{0,4})?$/)) {
+if (amt === '' || amt.match(/^(?!0\d)\d*\.?\d{0,4}$/)) {
  setMultiplierAmount(amt);
  runImportPreview();
+} else {
+  // Optionally handle invalid input
}

Line range hint 458-526: Enhance error handling in onImport

The error handling uses string concatenation which could be vulnerable to injection. Consider using template literals and structured error objects:

const createError = (type, details) => ({
  type,
  message: t(type, { ...details }),
  details
});

// Usage
if (date == null) {
  errorMessage = createError('INVALID_DATE', {
    date: trans.date || '(empty)',
    format: parseDateFormat
  });
  break;
}

Line range hint 749-766: Enhance form accessibility

The form controls lack proper accessibility attributes. Consider adding:

  1. ARIA labels for better screen reader support
  2. Proper form structure with fieldset and legend
  3. Error message association with form controls
 <View style={{ marginTop: 10 }}>
+  <form role="form" aria-label={t('Import Options')}>
+    <fieldset>
+      <legend>{t('CSV Options')}</legend>
       <Stack
         direction="row"
         align="flex-start"
         spacing={1}
         style={{ marginTop: 5 }}
       >
         {/* ... existing controls ... */}
       </Stack>
+    </fieldset>
+  </form>
 </View>
packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (1)

452-452: Consider extracting translation keys to constants

To improve maintainability and reduce the risk of typos in translation keys, consider extracting the translation keys to a separate constants file.

Example implementation:

+// translation-keys.js
+export const TRANSACTION_KEYS = {
+  AMOUNT: 'Amount',
+  PAYEE: 'Payee',
+  CATEGORY: 'Category',
+  NOTES: 'Notes',
+  DELETE: 'Delete transaction',
+  // ... other keys
+};

// TransactionEdit.jsx
-const { t } = useTranslation();
+const { t } = useTranslation();
+const { AMOUNT, PAYEE, CATEGORY, NOTES, DELETE } = TRANSACTION_KEYS;

This would make it easier to maintain translation keys and ensure consistency across the application.

packages/desktop-client/src/components/modals/EditRuleModal.jsx (2)

376-376: Consider translating additional UI strings.

While the translation hook is properly implemented, there are some hardcoded strings that should be translated for consistency:

  • "allocate" at line 447
  • "Add condition" at line 486

Apply this diff to improve internationalization:

-            {t('allocate')}
+            {t('Allocate')}
-      Add condition
+      {t('Add condition')}

Also applies to: 447-447, 486-486


Line range hint 508-517: Consider translating the tooltip content.

The tooltip text in the StageInfo component should be translated for consistency with the rest of the internationalization efforts.

Apply this diff to translate the tooltip content:

        content={
          <>
-            The stage of a rule allows you to force a specific order. Pre rules
-            always run first, and post rules always run last. Within each stage
-            rules are automatically ordered from least to most specific.
+            {t('The stage of a rule allows you to force a specific order. Pre rules always run first, and post rules always run last. Within each stage rules are automatically ordered from least to most specific.')}
          </>
        }
packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx (1)

70-70: Consider memoization for performance optimization

While the implementation is correct, consider using useMemo for translated strings that don't depend on dynamic values to optimize performance by preventing unnecessary re-renders.

Example optimization:

 const { t } = useTranslation();
+const staticLabels = useMemo(() => ({
+  budgeted: t('Budgeted'),
+  spent: t('Spent'),
+  balance: t('Balance')
+}), [t]);

Also applies to: 133-133, 231-231, 1145-1145, 1421-1421, 1642-1642, 1747-1747, 1973-1973

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c25e3d4 and e631668.

⛔ Files ignored due to path filters (1)
  • upcoming-release-notes/3893.md is excluded by !**/*.md
📒 Files selected for processing (55)
  • packages/desktop-client/src/components/ManageRulesPage.tsx (1 hunks)
  • packages/desktop-client/src/components/Notes.tsx (2 hunks)
  • packages/desktop-client/src/components/NotesButton.tsx (2 hunks)
  • packages/desktop-client/src/components/Notifications.tsx (2 hunks)
  • packages/desktop-client/src/components/ThemeSelector.tsx (2 hunks)
  • packages/desktop-client/src/components/Titlebar.tsx (3 hunks)
  • packages/desktop-client/src/components/accounts/AccountSyncCheck.tsx (3 hunks)
  • packages/desktop-client/src/components/common/Modal.tsx (4 hunks)
  • packages/desktop-client/src/components/mobile/MobileBackButton.tsx (2 hunks)
  • packages/desktop-client/src/components/mobile/accounts/Accounts.tsx (3 hunks)
  • packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx (10 hunks)
  • packages/desktop-client/src/components/mobile/transactions/AddTransactionButton.tsx (2 hunks)
  • packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (3 hunks)
  • packages/desktop-client/src/components/mobile/transactions/TransactionList.jsx (2 hunks)
  • packages/desktop-client/src/components/mobile/transactions/TransactionListWithBalances.jsx (3 hunks)
  • packages/desktop-client/src/components/modals/BudgetListModal.tsx (1 hunks)
  • packages/desktop-client/src/components/modals/CategoryAutocompleteModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/CategoryGroupMenuModal.tsx (3 hunks)
  • packages/desktop-client/src/components/modals/CategoryMenuModal.tsx (3 hunks)
  • packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/CreateLocalAccountModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/EditFieldModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/EditRuleModal.jsx (4 hunks)
  • packages/desktop-client/src/components/modals/EnvelopeBalanceMenuModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/EnvelopeBudgetMenuModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/GoCardlessInitialiseModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (2 hunks)
  • packages/desktop-client/src/components/modals/ManageRulesModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/MergeUnusedPayeesModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/ScheduledTransactionMenuModal.tsx (3 hunks)
  • packages/desktop-client/src/components/modals/SelectLinkedAccountsModal.jsx (3 hunks)
  • packages/desktop-client/src/components/modals/TrackingBalanceMenuModal.tsx (2 hunks)
  • packages/desktop-client/src/components/modals/TrackingBudgetMenuModal.tsx (2 hunks)
  • packages/desktop-client/src/components/reports/CategorySelector.tsx (2 hunks)
  • packages/desktop-client/src/components/reports/ReportSidebar.tsx (2 hunks)
  • packages/desktop-client/src/components/reports/ReportTopbar.tsx (2 hunks)
  • packages/desktop-client/src/components/reports/SaveReportName.tsx (2 hunks)
  • packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx (2 hunks)
  • packages/desktop-client/src/components/reports/reports/GetCardData.tsx (2 hunks)
  • packages/desktop-client/src/components/rules/ActionExpression.tsx (2 hunks)
  • packages/desktop-client/src/components/rules/RulesHeader.tsx (1 hunks)
  • packages/desktop-client/src/components/rules/Value.tsx (2 hunks)
  • packages/desktop-client/src/components/select/RecurringSchedulePicker.tsx (4 hunks)
  • packages/desktop-client/src/components/settings/BudgetTypeSettings.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/Export.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/FixSplits.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/Format.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/Reset.tsx (3 hunks)
  • packages/desktop-client/src/components/settings/Themes.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/UI.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/index.tsx (4 hunks)
  • packages/desktop-client/src/components/transactions/SimpleTransactionsTable.tsx (2 hunks)
  • packages/desktop-client/src/components/util/AmountInput.tsx (2 hunks)
🧰 Additional context used
📓 Learnings (3)
packages/desktop-client/src/components/mobile/accounts/Accounts.tsx (1)
Learnt from: qedi-r
PR: actualbudget/actual#3527
File: packages/desktop-client/src/components/accounts/Header.jsx:0-0
Timestamp: 2024-11-10T16:45:25.627Z
Learning: In the Actual Budget project, importing `t` directly from 'i18next' is acceptable and commonly used in the codebase.
packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx (1)
Learnt from: qedi-r
PR: actualbudget/actual#3527
File: packages/desktop-client/src/components/accounts/Header.jsx:0-0
Timestamp: 2024-11-10T16:45:25.627Z
Learning: In the Actual Budget project, importing `t` directly from 'i18next' is acceptable and commonly used in the codebase.
packages/desktop-client/src/components/modals/CreateLocalAccountModal.tsx (1)
Learnt from: qedi-r
PR: actualbudget/actual#3527
File: packages/desktop-client/src/components/modals/CreateLocalAccountModal.tsx:47-47
Timestamp: 2024-11-10T16:45:25.627Z
Learning: Validating balance is outside the scope in `CreateLocalAccountModal.tsx`.
🔇 Additional comments (121)
packages/desktop-client/src/components/ManageRulesPage.tsx (1)

2-2: LGTM! Clean implementation of the useTranslation hook.

The changes successfully replace the direct t import with the useTranslation hook, which will enable automatic re-rendering when the language changes. The implementation follows React hooks best practices and maintains the component's functionality while improving its internationalization support.

Also applies to: 8-8

packages/desktop-client/src/components/rules/RulesHeader.tsx (1)

2-2: LGTM! Clean migration to useTranslation hook

The changes correctly implement the migration from direct t import to useTranslation hook, following React hooks best practices and maintaining the existing translation functionality.

Also applies to: 8-8

packages/desktop-client/src/components/mobile/transactions/AddTransactionButton.tsx (1)

2-2: LGTM! Clean implementation of useTranslation hook.

The changes effectively implement the transition from direct t import to useTranslation hook while maintaining component functionality and following React best practices.

Also applies to: 19-19

packages/desktop-client/src/components/mobile/MobileBackButton.tsx (2)

2-2: LGTM: Clean import of useTranslation hook

The import statement follows React conventions and aligns with the PR objective to use hooks for translations.


Line range hint 41-41: Verify translation key existence

Ensure that the 'Back' translation key exists in all language files to prevent fallback to key name.

packages/desktop-client/src/components/modals/ManageRulesModal.tsx (2)

3-3: LGTM: Import of useTranslation hook

The import statement correctly introduces the useTranslation hook from react-i18next, aligning with the PR's objective to enhance internationalization support.


16-16: LGTM: Proper hook usage

The useTranslation hook is correctly implemented at the component's top level, following React hooks best practices. This implementation will enable automatic re-rendering when the language changes.

packages/desktop-client/src/components/modals/BudgetListModal.tsx (3)

2-2: LGTM: Import statement properly added

The useTranslation hook import is correctly placed with other React-related imports.


12-12: LGTM: Hook usage follows best practices

The useTranslation hook is properly implemented at the component's top level alongside other hooks.


Line range hint 24-24: Verify translation keys exist

Please ensure that the translation keys 'Switch Budget File' and 'Switching from:' exist in all language files.

Also applies to: 35-35

packages/desktop-client/src/components/ThemeSelector.tsx (2)

2-2: LGTM! Clean implementation of useTranslation hook.

The migration from direct t import to useTranslation hook is implemented correctly, following React hooks best practices and maintaining type safety.

Also applies to: 24-24


Line range hint 45-45: LGTM! Proper translation of accessibility attribute.

The aria-label is correctly internationalized using the t function, maintaining accessibility while adding language support.

packages/desktop-client/src/components/settings/BudgetTypeSettings.tsx (1)

2-2: LGTM! Correct implementation of useTranslation hook

The migration from direct t import to useTranslation hook is implemented correctly, following React hooks best practices.

Also applies to: 12-12

packages/desktop-client/src/components/settings/Export.tsx (3)

2-2: LGTM: Good migration to useTranslation hook

The addition of useTranslation import aligns with React best practices for internationalization, enabling automatic re-renders on language changes.


17-17: LGTM: Proper hook initialization

The useTranslation hook is correctly initialized at the component's top level, following React hooks best practices.


Line range hint 1-17: Verify complete removal of direct t import

Let's ensure there are no remaining direct imports of the t function in this file.

✅ Verification successful

Migration to useTranslation hook is correctly implemented

The verification shows that:

  • The file correctly imports useTranslation from 'react-i18next'
  • All usages of the t function are properly scoped through the hook's destructured t function
  • No direct imports of t from i18next remain
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining direct imports of t function
rg "import.*\{.*t.*\}.*from.*['\"]i18next['\"]" "packages/desktop-client/src/components/settings/Export.tsx"

Length of output: 112


Script:

#!/bin/bash
# Let's check for any i18next imports and their context
rg -A 3 "i18next" "packages/desktop-client/src/components/settings/Export.tsx"

# Also check for any usage of 't' function to ensure it's properly imported
rg -A 2 "\bt\(" "packages/desktop-client/src/components/settings/Export.tsx"

Length of output: 660

packages/desktop-client/src/components/settings/UI.tsx (3)

2-2: LGTM! Import change aligns with PR objectives

The addition of useTranslation hook import is consistent with the goal of replacing direct t function imports.


53-53: LGTM! Proper hook implementation

The useTranslation hook is correctly implemented at the component level.


Line range hint 53-93: Verify translation keys exist

Let's ensure the translation keys 'Advanced Settings' and 'Show advanced settings' are defined in the translation files.

packages/desktop-client/src/components/NotesButton.tsx (2)

8-8: LGTM! Clean import of useTranslation hook

The import follows the existing grouping pattern and aligns with the PR objective.


38-38: LGTM! Proper implementation of useTranslation hook

The hook is correctly implemented and follows React best practices:

  • Placed at the top of the component
  • Used to translate the aria-label, maintaining accessibility
  • Clean destructuring of the t function
packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx (1)

2-2: LGTM: Import of useTranslation hook

The addition of the useTranslation hook import aligns with the PR objective to enhance i18n support.

packages/desktop-client/src/components/settings/Reset.tsx (2)

2-2: LGTM: Import change aligns with best practices

The change from direct t import to useTranslation hook follows React best practices and enables automatic re-rendering on language changes.


14-14: LGTM: Proper hook implementation in ResetCache

The useTranslation hook is correctly implemented at the component level, maintaining React hooks rules and enabling component-level translation management.

packages/desktop-client/src/components/reports/SaveReportName.tsx (1)

3-3: LGTM: Clean import replacement

The replacement of the direct t import with useTranslation hook aligns with React best practices for i18n handling.

packages/desktop-client/src/components/settings/Themes.tsx (3)

2-2: LGTM: Import placement is correct

The useTranslation hook import is properly placed with other React-related imports.


40-40: LGTM: Hook usage follows best practices

The useTranslation hook is correctly implemented at the component's top level, following React hooks rules and the PR's standardization goals.


Line range hint 1-97: Verify consistent hook usage across settings components

Let's ensure this migration pattern is consistently applied across related components.

✅ Verification successful

Migration to useTranslation is consistently applied across settings components

The verification shows that all settings components are consistently using the useTranslation hook from 'react-i18next', and there are no direct imports of the t function from 'i18next'. The pattern is uniformly applied across all settings components including BudgetTypeSettings, Encryption, Export, FixSplits, Format, Reset, Themes, and UI components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining direct t imports in settings components
rg "import.*\{.*t.*\}.*from.*['\"]i18next['\"]" "packages/desktop-client/src/components/settings/"

# Check for consistent useTranslation usage pattern in settings components
rg "useTranslation" "packages/desktop-client/src/components/settings/"

Length of output: 2273

packages/desktop-client/src/components/modals/CategoryAutocompleteModal.tsx (2)

2-2: LGTM: Import of useTranslation hook

The import of useTranslation from 'react-i18next' is correctly implemented, aligning with the PR's objective to transition from direct t function imports.


30-30: LGTM: Proper hook initialization

The useTranslation hook is correctly initialized at the component's top level, following React hooks best practices.

packages/desktop-client/src/components/modals/TrackingBalanceMenuModal.tsx (3)

5-5: LGTM: Import statement aligns with PR objectives

The addition of useTranslation hook import is correct and follows the PR's goal of standardizing translation handling.


41-41: LGTM: Proper hook implementation

The useTranslation hook is correctly implemented at the component level, following React hooks rules and providing access to the translation function.


Line range hint 65-67: Consider comprehensive internationalization

While the "Balance" text is now properly translated, consider reviewing other potential internationalization opportunities in the component:

  • Modal title (category.name) might need translation depending on the data source
  • Future error states could benefit from translated messages instead of returning null

Let's check for other potential translation opportunities in similar modal components:

packages/desktop-client/src/components/modals/EnvelopeBalanceMenuModal.tsx (3)

5-5: LGTM: Clean import of useTranslation hook

The import is correctly placed and aligns with the PR objective to use the useTranslation hook.


43-43: LGTM: Proper hook usage

The useTranslation hook is correctly implemented at the component's top level, following React hooks best practices.


Line range hint 71-71: LGTM: Translation implementation

The translation is correctly implemented for the "Balance" string.

Let's check for any other potential strings that might need translation in this component:

✅ Verification successful

All strings are properly internationalized

After reviewing the component's source code, I can confirm that there are no hardcoded strings that require translation. The only visible text content "Balance" is already properly translated using the t() function. Other text content in the component is either:

  1. Dynamically loaded from variables (like category.name)
  2. Handled by child components (BalanceWithCarryover, BalanceMenu, etc.)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential hardcoded strings in the component that might need translation
rg -U --type typescript --type tsx "(<Text[^>]*>([^{<>]|[^<]{[^t][^}]*})*</Text>|title=(\{[^t][^}]*\}|\"[^\"]*\"))" packages/desktop-client/src/components/modals/EnvelopeBalanceMenuModal.tsx

Length of output: 372


Script:

#!/bin/bash
# Let's try a simpler approach to find potential hardcoded strings
# Look for Text components and string literals
rg --type typescript --type tsx -U "Text|['\"][^'\"]+['\"]" packages/desktop-client/src/components/modals/EnvelopeBalanceMenuModal.tsx

Length of output: 177


Script:

#!/bin/bash
# Let's try without file type specification and look at the file content
cat packages/desktop-client/src/components/modals/EnvelopeBalanceMenuModal.tsx

Length of output: 3233

packages/desktop-client/src/components/Notes.tsx (2)

3-3: LGTM! Import placement is correct.

The useTranslation hook import is properly placed with other React-related imports.


102-102: LGTM! Hook usage follows best practices.

The implementation:

  • Correctly uses the useTranslation hook at the component level
  • Properly extracts the t function
  • Effectively applies it to translate the placeholder text

Let's verify that all user-facing strings in this component are properly translated:

Also applies to: 126-126

✅ Verification successful

All user-facing strings are properly translated in this component

The verification confirms that:

  • The only user-facing string in the component is "Notes (markdown supported)" which is correctly wrapped in the translation function t()
  • All other string literals in the file are related to styling properties or technical configurations
  • The component follows translation best practices consistently
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any hardcoded strings that might need translation
rg -U "(?<![a-zA-Z])'[^']*'|(?<![a-zA-Z])\"[^\"]*\"" "packages/desktop-client/src/components/Notes.tsx" \
  | grep -v "^import\|^\/\/\|className\|^const\|border\|backgroundColor\|color\|linkTarget\|display\|margin\|padding\|overflowWrap\|outline\|^    '\|^  '\|^}'\|^{'\|borderLeft\|borderTop\|borderRight\|borderBottom"

Length of output: 580


Script:

#!/bin/bash
# Search for any hardcoded strings that might need translation using PCRE2
rg --pcre2 "(?<![a-zA-Z])'[^']*'|(?<![a-zA-Z])\"[^\"]*\"" "packages/desktop-client/src/components/Notes.tsx" -A 2 \
  | grep -v "^import\|^\/\/\|className\|^const\|border\|backgroundColor\|color\|linkTarget\|display\|margin\|padding\|overflowWrap\|outline\|^    '\|^  '\|^}'\|^{'\|borderLeft\|borderTop\|borderRight\|borderBottom"

# Also let's check for t() function usage to see translation coverage
rg "t\(['\"].*?['\"]\)" "packages/desktop-client/src/components/Notes.tsx" -A 1

Length of output: 991

packages/desktop-client/src/components/modals/ScheduledTransactionMenuModal.tsx (3)

6-6: LGTM! Proper implementation of useTranslation hook.

The hook is correctly imported and initialized at the component level, following React hooks best practices.

Also applies to: 30-30


101-101: LGTM! Proper hook initialization in ScheduledTransactionMenu.

The useTranslation hook is correctly initialized at the component level.


Line range hint 117-124: Verify menu item translation keys.

The translation keys 'Post transaction' and 'Skip scheduled date' are used for menu items.

packages/desktop-client/src/components/modals/EnvelopeBudgetMenuModal.tsx (3)

7-7: LGTM: Import change aligns with PR objectives

The addition of useTranslation hook import is correct and follows the PR's goal of standardizing translation handling.


47-47: LGTM: Hook usage follows best practices

The useTranslation hook is correctly implemented at the top level of the component alongside other hooks, following React hooks best practices.


Line range hint 89-89: Verify translation coverage for all user-facing strings

While the "Budgeted" string is correctly translated, let's ensure all user-facing strings in the modal are handled by the translation system.

packages/desktop-client/src/components/modals/TrackingBudgetMenuModal.tsx (3)

7-7: LGTM! Import change aligns with project objectives.

The addition of the useTranslation hook import follows React best practices and aligns with the PR's goal of improving localization handling.


47-47: LGTM! Hook implementation follows best practices.

The useTranslation hook is correctly initialized at the component's top level, following React hooks rules.


Line range hint 23-35: Consider adding null checks for optional props.

While the new props are correctly typed, they're passed directly to BudgetMenu without checking for undefined values. This could lead to runtime errors if the props aren't provided.

Let's verify how these props are handled in the BudgetMenu component:

Consider adding null checks or providing default values:

export function TrackingBudgetMenuModal({
  categoryId,
  onUpdateBudget,
  onCopyLastMonthAverage,
  onSetMonthsAverage,
  onApplyBudgetTemplate,
}: TrackingBudgetMenuModalProps) {
  // ...
  return (
    // ...
    <BudgetMenu
      getItemStyle={() => defaultMenuItemStyle}
-     onCopyLastMonthAverage={onCopyLastMonthAverage}
-     onSetMonthsAverage={onSetMonthsAverage}
-     onApplyBudgetTemplate={onApplyBudgetTemplate}
+     onCopyLastMonthAverage={onCopyLastMonthAverage ?? (() => {})}
+     onSetMonthsAverage={onSetMonthsAverage ?? (() => {})}
+     onApplyBudgetTemplate={onApplyBudgetTemplate ?? (() => {})}
    />
  );
}
packages/desktop-client/src/components/settings/FixSplits.tsx (2)

2-2: LGTM: Import statement correctly added

The useTranslation hook import is properly placed and aligns with the PR objective of improving i18n support.


57-57: LGTM: Hook implementation is correct

The useTranslation hook is properly implemented at the component level.

packages/desktop-client/src/components/rules/ActionExpression.tsx (2)

2-2: LGTM: Import change aligns with PR objectives

The change from direct t import to useTranslation hook is correctly implemented.


Line range hint 4-17: Verify translation setup for imported utilities

Let's verify if friendlyOp and ALLOCATION_METHODS are prepared for internationalization.

packages/desktop-client/src/components/modals/GoCardlessInitialiseModal.tsx (3)

3-3: LGTM! Proper implementation of useTranslation hook

The migration from direct t import to useTranslation hook is implemented correctly, following React best practices.

Also applies to: 29-29


1-1: Consider addressing TypeScript strict mode issues

The @ts-strict-ignore comment suggests there are TypeScript strict mode violations that should be addressed for better type safety.

Let's check for TypeScript configuration and similar patterns:


Line range hint 1-140: Verify translation key definitions

Let's ensure all translation keys used in this component are defined in the translation files.

packages/desktop-client/src/components/settings/Format.tsx (3)

3-3: LGTM: Correct implementation of useTranslation import

The addition of useTranslation hook import aligns with React best practices for internationalization.


60-60: LGTM: Proper hook initialization

The useTranslation hook is correctly initialized at the component's top level, following React hooks best practices.


Line range hint 89-89: LGTM: Comprehensive translation implementation

All user-facing strings are properly wrapped with the t() function, ensuring consistent internationalization throughout the component.

Let's verify that all user-facing strings are properly translated:

Also applies to: 108-108, 122-122, 134-134, 147-147, 156-160

✅ Verification successful

All user-facing strings are properly translated

The verification shows that all user-facing text content is properly handled:

  • Column titles are passed through the t() function
  • The "Hide decimal places" label uses t()
  • The "Formatting" text and its description use t()
  • Day names and date formats are handled through structured data (daysOfWeek and dateFormats arrays)
  • Number formats are imported from core utilities (numberFormats)

The only non-translated strings found are:

  • Technical IDs (e.g., "settings-textDecimal")
  • CSS class names and style properties
  • Variable names and technical constants
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any hardcoded strings that might have been missed in translation
# Look for string literals in JSX that aren't wrapped in t()

ast-grep --pattern 'JSXText {
  $text
}' packages/desktop-client/src/components/settings/Format.tsx

# Also check for potential string literals in component props
ast-grep --pattern 'JSXAttribute {
  $name="$value"
}'  packages/desktop-client/src/components/settings/Format.tsx

Length of output: 217


Script:

#!/bin/bash
# Let's try a different approach to check for text content and string literals
# First, let's see the actual content of the file
cat packages/desktop-client/src/components/settings/Format.tsx

# Then let's specifically look for potential untranslated strings using ripgrep
# This will show us string literals in JSX context with surrounding lines
rg -U ">[^<]*[a-zA-Z]" packages/desktop-client/src/components/settings/Format.tsx

# Also look for string literals in props that might need translation
rg "=['\"](.*?)['\"]" packages/desktop-client/src/components/settings/Format.tsx

Length of output: 6984

packages/desktop-client/src/components/util/AmountInput.tsx (1)

11-11: LGTM: Import change aligns with PR objectives

The change from direct t function import to useTranslation hook follows React best practices and enables automatic re-rendering on language changes.

packages/desktop-client/src/components/rules/Value.tsx (2)

3-3: LGTM: Proper implementation of useTranslation hook

The addition of useTranslation hook and its usage follows React hooks best practices and aligns with the PR objectives.

Also applies to: 39-39


Line range hint 156-162: Verify consistent translation usage across components

Let's verify if the translation key 'and' is used consistently across other components that might have similar "in between" functionality.

packages/desktop-client/src/components/mobile/transactions/TransactionListWithBalances.jsx (2)

2-2: LGTM: Import change aligns with PR objectives

The change from direct t import to useTranslation hook follows React best practices and enables automatic re-rendering on language changes.


174-174: Maintain consistent translation key structure

Similar to the previous component, consider using a more specific translation key like 'transactions.balance.total' for consistency.

Let's verify the translation keys usage across the codebase:

packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx (2)

2-2: LGTM: Import statement follows conventions

The addition of the useTranslation hook import aligns with the PR objective and follows proper import conventions.


39-40: LGTM: Hook usage follows React best practices

The useTranslation hook is correctly implemented at the component's top level, following React hooks best practices.

packages/desktop-client/src/components/accounts/AccountSyncCheck.tsx (2)

2-2: LGTM: Import changes align with PR objectives.

The addition of useTranslation import is appropriate for the intended refactoring.


90-90: LGTM: Clean integration of useErrorMessage hook.

The hook integration is well-implemented and maintains the existing component functionality.

packages/desktop-client/src/components/reports/reports/GetCardData.tsx (1)

3-3: LGTM: Import statement is correctly placed and used

The addition of the useTranslation hook import aligns with the PR objective of migrating from direct t function imports to hook-based translations.

packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx (4)

4-4: LGTM: Proper implementation of useTranslation hook

The migration from direct t import to useTranslation hook follows React best practices and aligns with the PR objectives.

Also applies to: 35-35


Line range hint 63-64: LGTM: Consistent translation implementation

The translation strings are properly implemented using the useTranslation hook throughout the component. The usage is consistent and follows i18n best practices.

Also applies to: 77-83, 89-95, 142-142, 165-165, 181-181, 186-186


Line range hint 43-43: Verify error state handling with null value

The error state is now set to null instead of an empty string. While the error display logic appears to handle this correctly through the conditional rendering, please verify that all error state consumers handle both empty string and null values consistently.

Also applies to: 123-134

✅ Verification successful

Let me check how these error states are consumed in the UI to ensure consistent handling.


Error state handling is consistent across modal components

The codebase consistently handles error states using conditional rendering with the && operator, which safely handles both null and empty string values. All modal components follow the same pattern where:

  • Error states are explicitly set to null when clearing errors
  • Error messages are rendered only when the error state is truthy
  • The change from empty string to null aligns with the prevalent pattern across other modals
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other uses of setError in similar modal components
rg "setError\(" packages/desktop-client/src/components/modals/

Length of output: 2025


Script:

#!/bin/bash
# Search for error rendering patterns in modal components
rg -A 2 "error\s*[?&]" packages/desktop-client/src/components/modals/

# Also search for error type declarations
ast-grep --pattern 'error: $_'

Length of output: 4655


Line range hint 147-157: Review password visibility toggle implementation

While the password visibility toggle is a common UX pattern, ensure it follows security best practices:

  1. Consider auto-hiding the password after a timeout
  2. Ensure the password state is properly cleared on component unmount
✅ Verification successful

Let me check the implementation details of these components to verify the security practices.


Let me check the complete implementation of these components to better understand the password handling.


Password visibility toggle implementation is secure and consistent

After reviewing the implementation across all password-related components, I can confirm that:

  1. The password visibility toggle follows a consistent pattern across all components
  2. The password state is managed locally using React's useState and is automatically cleaned up when components unmount
  3. The implementation is used in appropriate contexts (encryption key setup and password confirmation)
  4. The password visibility state is not persisted and defaults to hidden on mount

While auto-hiding after timeout could be an enhancement, the current implementation is secure as:

  • It requires explicit user action to show/hide
  • The visibility state resets when the modal is closed
  • The implementation is used only in modal contexts where the user is actively engaged
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar password visibility implementations to ensure consistency
rg "setShowPassword|showPassword.*password" packages/desktop-client/src/

Length of output: 1409


Script:

#!/bin/bash
# Check the cleanup/unmount handling in these components
ast-grep --pattern 'useEffect($$$) {
  $$$
  return () => {
    $$$
  }
}'  packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx

# Check for timeout-based auto-hide implementations
rg "setTimeout.*setShowPassword" packages/desktop-client/src/

Length of output: 368


Script:

#!/bin/bash
# Get the full content of the password-related components
cat packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx
cat packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx
cat packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx

# Check for any password-related security utilities
rg -A 3 "password.*security|security.*password" packages/desktop-client/src/

Length of output: 15870

packages/desktop-client/src/components/settings/index.tsx (4)

2-2: LGTM: Proper implementation of useTranslation hook

The useTranslation hook is correctly imported and initialized in the component, following React hooks best practices.

Also applies to: 38-38


99-99: LGTM: Proper implementation of useTranslation hook

The useTranslation hook is correctly initialized and all user-facing strings are properly wrapped with the translation function.


129-129: LGTM: Proper implementation of useTranslation hook

The useTranslation hook is correctly initialized and all user-facing strings are properly wrapped with the translation function. The component's core functionality for handling preferences and budget management remains intact.


38-38: Verify consistency of translation keys

Let's verify that the translation keys used in this file are consistent with their usage across the codebase.

Also applies to: 99-99, 129-129

✅ Verification successful

Based on the verification results, I can now provide a final response:

Translation keys are consistently used

The translation keys in the settings component are simple, descriptive, and consistently used. They follow a clear pattern:

  • Basic UI elements: 'Settings', 'Budget Name', 'Close Budget'
  • App information: 'Actual', 'Release Notes'
  • Status messages: 'You're up to date!', 'New version available:'
  • Technical identifiers: 'IDs', 'Budget ID:', 'Sync ID:'

All keys are properly wrapped in the t() function from the useTranslation hook, and their usage is straightforward and maintainable.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistency in translation key usage

# Search for translation keys used in this file
echo "Searching for translation keys usage..."
rg "t\(['\"](?:Actual|Settings|Budget Name|Close Budget|You're up to date!|New version available:|Release Notes|IDs|Budget ID:|Sync ID:)" \
   --type ts \
   --type tsx \
   -g '!*.test.*' \
   -g '!**/locales/**'

Length of output: 317


Script:

#!/bin/bash
# Let's first check the content of the settings component to identify the actual translation keys used
echo "Content of settings component:"
cat "packages/desktop-client/src/components/settings/index.tsx"

# Then we'll search for translation key usage across the codebase
# Note: Using simpler rg command without file type filters since tsx wasn't recognized
echo -e "\nSearching for translation key usage across the codebase:"
rg "t\(['\"]" -g "!**/locales/**" -g "!*.test.*"

Length of output: 100955


Script:

#!/bin/bash
# Let's check the translation keys used in the settings component and verify their usage
echo "Checking translation keys in settings/index.tsx:"
rg -A 1 "t\(['\"]" "packages/desktop-client/src/components/settings/index.tsx"

# Let's also check the translation files to ensure these keys are defined
echo -e "\nChecking translation files:"
fd ".*\.(json|po|yaml|yml)" "packages/desktop-client/src/locales" || true

Length of output: 1197

packages/desktop-client/src/components/reports/ReportTopbar.tsx (1)

2-2: LGTM! Proper implementation of useTranslation hook

The change from direct t import to useTranslation hook is implemented correctly. This will enable automatic re-rendering when the language changes, improving the internationalization support.

Also applies to: 55-55

packages/desktop-client/src/components/modals/CategoryMenuModal.tsx (4)

3-3: LGTM: Import changes align with PR objectives.

The addition of useTranslation hook import and removal of direct t function import follows React best practices for internationalization.


42-42: LGTM: Proper implementation of useTranslation hook.

The hook is correctly initialized at the component level and properly used for translating the button text.

Also applies to: 142-142


Line range hint 47-53: LGTM: Improved validation in onRename function.

Good improvement in the onRename function to prevent unnecessary saves when the name hasn't changed.


161-161: LGTM: Proper implementation of useTranslation hook and accessibility.

The hook is correctly initialized and properly used for the Menu button's aria-label.

Also applies to: 180-180

packages/desktop-client/src/components/modals/CreateLocalAccountModal.tsx (1)

4-4: LGTM! Successfully integrated useTranslation hook.

The changes align with the PR objective, replacing direct import of t with the useTranslation hook. This will enable automatic re-rendering when the language changes.

Also applies to: 32-32

packages/desktop-client/src/components/modals/MergeUnusedPayeesModal.tsx (3)

2-2: LGTM: Translation hook import added correctly

The addition of the useTranslation hook import aligns with the PR objectives and follows React best practices.


29-29: LGTM: Translation hook initialized correctly

The useTranslation hook is properly initialized at the component's top level, following React hooks best practices.


Line range hint 180-200: LGTM: Button texts properly internationalized

All button labels are correctly wrapped with the translation function, ensuring consistent internationalization.

packages/desktop-client/src/components/modals/CategoryGroupMenuModal.tsx (2)

8-8: LGTM: Import of useTranslation hook

The addition of the useTranslation hook import aligns with the PR objective and follows React best practices.


49-49: LGTM: Proper implementation of useTranslation hook

The hook is correctly implemented at the component level and properly used for translating user-facing strings. The changes follow React hooks best practices and maintain component functionality.

Also applies to: 164-164, 172-172

packages/desktop-client/src/components/transactions/SimpleTransactionsTable.tsx (2)

8-8: LGTM: Import of useTranslation hook

The addition of the useTranslation hook import aligns with the PR objective of improving localization handling.


168-168: LGTM: Proper hook initialization

The useTranslation hook is correctly initialized at the component level, following React hooks best practices.

packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx (1)

4-4: LGTM: Translation hook integration

The useTranslation hook is correctly imported and initialized, aligning with the PR's objective to enhance internationalization support.

Also applies to: 38-38

packages/desktop-client/src/components/modals/SelectLinkedAccountsModal.jsx (2)

2-2: LGTM: Import of useTranslation hook

The addition of the useTranslation hook import aligns with the PR objective and follows proper import organization.


34-34: LGTM: Proper initialization of useTranslation hook

The hook is correctly initialized at the component level, and all translations are properly handled using the hook's t function.

✅ Verification successful

Translation hook is correctly used throughout the component

The verification confirms that the useTranslation hook's t function is consistently used across the component for all user-facing strings, including:

  • Modal title and navigation elements
  • Table column headers
  • Action button labels
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify consistent usage of useTranslation across the component
rg "t\(['\"]" packages/desktop-client/src/components/modals/SelectLinkedAccountsModal.jsx -A 1

Length of output: 634

packages/desktop-client/src/components/modals/EditFieldModal.tsx (2)

7-7: LGTM: Proper implementation of useTranslation hook

The addition of the useTranslation hook and its initialization follows React best practices and aligns with the PR objectives.

Also applies to: 48-48


Line range hint 89-89: LGTM: Consistent translation of field labels

The translation of field labels is implemented consistently across all field types using the t function.

Also applies to: 108-108, 201-201

packages/desktop-client/src/components/Notifications.tsx (2)

9-9: LGTM: Import statement aligns with PR objective.

The addition of the useTranslation hook import is appropriate for the intended migration from direct t function imports.


94-94: LGTM: Hook usage follows React best practices.

The useTranslation hook is correctly implemented at the component level, enabling automatic re-renders on language changes.

packages/desktop-client/src/components/reports/CategorySelector.tsx (3)

3-3: LGTM: Import change aligns with React best practices

The change from direct t import to useTranslation hook follows React best practices and matches the PR objectives.


36-36: LGTM: Hook usage follows React conventions

The useTranslation hook is correctly implemented at the component's top level, following React's rules of hooks.


Line range hint 1-215: Verify consistent translation pattern usage

Let's verify that similar category selection UI components follow the same translation pattern.

✅ Verification successful

Translation patterns are consistently implemented

All components that use the CategorySelector or handle category-related functionality properly implement translations using the useTranslation hook from react-i18next. The CategorySelector component and its related components (ReportSidebar, TransferModal, CoverModal, ConfirmCategoryDeleteModal, CloseAccountModal) all follow the same translation pattern, using the hook to access the translation function and properly translating all user-facing strings.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar category selection components that might need the same translation pattern
rg -t typescript -t javascript "CategorySelector|categoryGroups.*categories" packages/desktop-client/src/

Length of output: 142


Script:

#!/bin/bash
# Search for similar category selection components and their translation patterns
rg --type-add 'ts:*.{ts,tsx}' --type-add 'js:*.{js,jsx}' -t ts -t js "CategorySelector|categoryGroups.*categories" packages/desktop-client/src/

Length of output: 1889


Script:

#!/bin/bash
# Let's check the usage of translation in these components
rg --type-add 'ts:*.{ts,tsx}' --type-add 'js:*.{js,jsx}' -t ts -t js -B 2 -A 2 "useTranslation|t\(['\"]" packages/desktop-client/src/components/reports/ReportSidebar.tsx packages/desktop-client/src/components/modals/TransferModal.tsx packages/desktop-client/src/components/modals/CoverModal.tsx packages/desktop-client/src/components/modals/ConfirmCategoryDeleteModal.tsx packages/desktop-client/src/components/modals/CloseAccountModal.tsx

Length of output: 25349

packages/desktop-client/src/components/mobile/accounts/Accounts.tsx (2)

2-2: LGTM! Import change aligns with PR objectives.

The addition of useTranslation import is appropriate and consistent with the goal of improving internationalization support.


Line range hint 198-219: LGTM! Comprehensive translation implementation.

The translation implementation is well done:

  • Hook is correctly placed at the component level
  • Both visible text and accessibility labels are properly translated
  • Maintains existing component functionality
packages/desktop-client/src/components/Titlebar.tsx (2)

3-3: LGTM: Import statement follows conventions

The addition of the useTranslation hook import is correctly placed and aligns with the PR's objective.


269-269: LGTM: Proper implementation of translations

The translation hook is correctly implemented and all user-facing strings are properly translated using the t function.

Also applies to: 306-306, 342-342

packages/desktop-client/src/components/common/Modal.tsx (3)

17-17: LGTM: Proper integration of useTranslation hook

The hook is correctly imported and initialized at the component level, following React hooks best practices.

Also applies to: 57-57


304-304: LGTM: Good accessibility enhancement

The translation of the logo's aria-label improves accessibility for screen readers while maintaining proper i18n practices.

Also applies to: 339-345


Line range hint 473-481: LGTM: Consistent translation implementation

The close button's aria-label translation is properly implemented. Let's verify the translation key usage across the codebase for consistency.

✅ Verification successful

Translation key 'Close' is consistently implemented across components

The verification shows that the 'Close' translation key is consistently used in similar contexts across the codebase:

  • Modal.tsx: Close button with translated aria-label
  • Notifications.tsx: Close button with translated aria-label
  • UpdateNotification.tsx: Close button with translated aria-label

There is only one instance (in Upcoming.tsx) that uses a hardcoded English string, but it's a different use case with a more specific context "Close upcoming length settings".

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of the 'Close' translation key across the codebase

# Search for other occurrences of the 'Close' translation key
rg "t\(['\"]Close['\"]\)" --type ts --type tsx

# Search for similar close button implementations
ast-grep --pattern 'Button {
  $$$
  aria-label={$_}
  $$$
}'

Length of output: 144


Script:

#!/bin/bash
# Let's try a different approach to search for translation keys and button implementations

# Search for 'Close' translation key usage with more flexible pattern
rg "t\(['\"](Close|close)['\"]" 

# Search for aria-label usage in buttons with more flexible pattern
rg "aria-label.*Close" 

# Search for Button components with aria-label
ast-grep --pattern 'Button $$$aria-label={$_}$$$'

Length of output: 787

packages/desktop-client/src/components/mobile/transactions/TransactionList.jsx (2)

9-9: LGTM: Import statement follows project conventions

The addition of the useTranslation hook import aligns with the PR objective and follows the existing import organization pattern.


49-49: LGTM: Proper implementation of useTranslation hook

The useTranslation hook is correctly initialized at the component level and properly used for internationalizing the loading text. This implementation follows React hooks best practices and aligns with the PR objectives.

Also applies to: 92-92

packages/desktop-client/src/components/select/RecurringSchedulePicker.tsx (2)

9-9: LGTM: Import of useTranslation hook

The addition of the useTranslation hook import aligns with the PR objective of replacing direct t function imports.


558-558: LGTM: Clean implementation of translations

The translation implementation in the RecurringSchedulePicker component is clean and follows React best practices. The conditional rendering with translations is handled appropriately.

Also applies to: 576-579

packages/desktop-client/src/components/reports/ReportSidebar.tsx (3)

2-2: LGTM: Import change aligns with PR objectives

The addition of useTranslation hook import is appropriate and follows React's import organization pattern.


92-92: LGTM: Proper hook initialization

The useTranslation hook is correctly initialized at the component level, following React hooks best practices.


91-91: Verify the new default prop value

A default value of false has been added for isComplexCategoryCondition. While this is a good practice, it wasn't mentioned in the PR objectives.

✅ Verification successful

Based on the search results, I can generate the final response as I have enough context to verify the concern. The results show that:

  1. The prop is defined in ReportSidebar.tsx with an optional type and a default value of false
  2. It's used within CustomReport.tsx where it's computed based on category conditions
  3. The prop is passed from CustomReport to ReportSidebar and used to conditionally render an information message

Default prop value is justified and aligns with the codebase

The default value of false for isComplexCategoryCondition is actually necessary as it's used to control the visibility of an information message about category filters. The prop is properly integrated into the codebase's logic, where CustomReport component computes this value based on the complexity of category conditions and passes it to the sidebar. This is a valid implementation detail rather than an unnecessary addition.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if this prop is used elsewhere in the codebase
rg "isComplexCategoryCondition" -A 3 -B 3

Length of output: 3639

packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (1)

138-138: Verify translation coverage

The change to use useTranslation hook is good, but let's verify all strings are properly wrapped with the translation function.

✅ Verification successful

Let me generate another script to specifically check the ImportTransactionsModal component for any untranslated strings:


Let me try another script to specifically check for untranslated strings in the ImportTransactionsModal component:


Let me try a simpler approach to check for untranslated strings:


Based on the code inspection and the results from the shell scripts, I can now provide the final response:

Translation implementation is properly done

All user-facing strings in the ImportTransactionsModal component are properly wrapped with the translation function t(). The component correctly:

  • Uses the useTranslation hook from react-i18next
  • Wraps all user-facing strings with t() function
  • Uses Trans component for complex text content
  • Only contains untranslated strings in HTML attributes (ids, types) which don't need translation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find potentially untranslated strings in JSX
rg -g '*.jsx' -g '*.js' '\b(title|label|placeholder)=[{"](?!.*\bt\()'

# Find hardcoded strings in JSX text nodes
rg -g '*.jsx' -g '*.js' '>\s*[A-Z][a-zA-Z\s]+\s*<'

Length of output: 2026


Script:

#!/bin/bash
# Check for text content in ImportTransactionsModal
cat packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx

# Also search for potential string literals in the same file
rg --pcre2 '"[^"]*"|\'[^\']*\'' packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx

Length of output: 34104


Script:

#!/bin/bash
# Search for string literals that might need translation
rg --pcre2 '(?<!t\()["\']([\w\s]+)["\']' packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx

# Also check for text content in JSX that might need translation
rg --pcre2 '>\s*[A-Za-z][\w\s]+\s*<' packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx

Length of output: 321


Script:

#!/bin/bash
# Look for string literals in the file
rg --pcre2 '"[^"]*"' packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx

# Look for text content in JSX
rg --pcre2 '>[^<>]+<' packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx

Length of output: 852

packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (3)

10-10: LGTM: Clean import of useTranslation hook

The addition of the useTranslation hook import aligns with the PR objective of improving internationalization support.


293-293: LGTM: Proper implementation of translations in ChildTransactionEdit

The useTranslation hook is correctly initialized and consistently applied to all user-facing strings in the component, including field labels for Payee, Amount, Category, Notes, and the Delete split button.

Also applies to: 316-316, 341-341, 380-380, 440-440


452-452: LGTM: Comprehensive translation implementation in TransactionEditInner

The useTranslation hook is properly initialized and consistently applied to all user-facing strings throughout the component, including field labels, button texts, and status messages.

Also applies to: 799-799, 824-824, 847-847, 873-873, 891-891, 907-907, 927-927, 947-947, 967-967, 1001-1001

packages/desktop-client/src/components/modals/EditRuleModal.jsx (3)

306-306: LGTM! Proper implementation of useTranslation hook.

The hook is correctly imported and used at the component level.


765-765: LGTM! Proper implementation of useTranslation hook.

The hook is correctly imported and used at the component level.


Line range hint 1-1200: Verify translation key consistency across the application.

The implementation of useTranslation looks good, but we should verify that the translation keys are consistent with other parts of the application.

Run the following script to check translation key usage:

✅ Verification successful

Based on the shell script results showing translation key usage across the codebase, I can now generate the final response:

Translation keys are consistently used across the application

The review comment's concern about translation key consistency has been verified. The codebase shows extensive and consistent use of the t() function from react-i18next across components, with proper key naming patterns and parameter handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistency in translation key usage across the application

# Search for translation key usage patterns
rg -g '*.{js,jsx,ts,tsx}' "t\(['\"]" --json | jq -r '.data.lines.text' | sort | uniq

Length of output: 84831

packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx (2)

2-2: LGTM: Import of useTranslation hook

The addition of useTranslation hook import aligns with the PR's objective to improve internationalization handling.


70-70: Well-structured implementation of useTranslation hook

The hook is consistently implemented across all components, properly handling both UI text and accessibility labels. This systematic approach ensures:

  • Consistent translation handling
  • Improved accessibility through translated aria-labels
  • Better maintainability with centralized translation management

Also applies to: 133-133, 231-231, 1145-1145, 1421-1421, 1642-1642, 1747-1747, 1973-1973

@@ -1,6 +1,5 @@
import React, { useState } from 'react';

import { t } from 'i18next';
import { useTranslation } from 'react-i18next';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Inconsistent translation import patterns detected

The codebase shows mixed usage of translation imports:

  • Direct t imports from 'i18next' in 6 files:
    • packages/desktop-client/src/components/util/accountValidation.ts
    • packages/desktop-client/src/components/schedules/ScheduleDetails.jsx
    • packages/desktop-client/src/components/reports/disabledList.ts
    • packages/desktop-client/src/components/reports/ReportOptions.ts
    • packages/desktop-client/src/components/budget/util.ts
    • packages/desktop-client/src/components/accounts/Account.tsx

These files should be updated to use the useTranslation hook for consistency with the rest of the codebase, which predominantly uses the hook pattern.

🔗 Analysis chain

Verify consistent useTranslation implementation

Let's verify that this pattern is consistently applied across other components in the codebase.

Also applies to: 14-14, 42-42

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining direct imports of the t function
rg "import.*\{.*t.*\}.*from 'i18next'" packages/desktop-client/src/

# Search for useTranslation usage pattern
rg "const.*\{.*t.*\}.*=.*useTranslation\(\)" packages/desktop-client/src/

Length of output: 23741

Comment on lines +40 to +41
const { t } = useTranslation();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Migration to useTranslation hook needs completion

The verification reveals inconsistent translation implementation across the codebase:

  • Several files still use direct import { t } from 'i18next' which should be migrated to useTranslation hook:
    • packages/desktop-client/src/components/schedules/ScheduleDetails.jsx
    • packages/desktop-client/src/components/util/accountValidation.ts
    • packages/desktop-client/src/components/reports/ReportOptions.ts
    • packages/desktop-client/src/components/reports/disabledList.ts
    • packages/desktop-client/src/components/budget/util.ts
    • packages/desktop-client/src/components/accounts/Account.tsx
🔗 Analysis chain

LGTM: Proper hook implementation

The useTranslation hook is correctly implemented at the top level of the component, following React hooks rules. The destructured t function maintains the same usage pattern as before.

Let's verify that this pattern is consistently applied across other components:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining direct imports of 't' from i18next
# and verify consistent usage of useTranslation hook

# Check for any remaining direct 't' imports from i18next
echo "Checking for remaining direct 't' imports from i18next..."
rg "import.*\{.*t.*\}.*from 'i18next'" packages/desktop-client/src/

# Verify useTranslation hook usage pattern
echo "Verifying useTranslation hook usage pattern..."
ast-grep --pattern 'const { t } = useTranslation();'

Length of output: 24564

@@ -107,6 +107,7 @@ type SyncButtonProps = {
isMobile?: boolean;
};
function SyncButton({ style, isMobile = false }: SyncButtonProps) {
const { t } = useTranslation();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add translations for all user-facing strings

While the aria-label is now translated, there are other user-facing strings that should also be translated for consistency:

      <Text style={isMobile ? { ...mobileTextStyle } : { marginLeft: 3 }}>
        {syncState === 'disabled'
-         ? 'Disabled'
-         : syncState === 'offline'
-           ? 'Offline'
-           : 'Sync'}
+         ? t('Disabled')
+         : syncState === 'offline'
+           ? t('Offline')
+           : t('Sync')}
      </Text>

Also applies to: 208-224

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant