diff --git a/packages/desktop-client/src/components/filters/FilterExpression.tsx b/packages/desktop-client/src/components/filters/FilterExpression.tsx index 55accb1c818545cf5a672bf1ba72c4bd509ee12d..d649fd09c3f7375469af5f2c461ac6748bc7dd8f 100644 --- a/packages/desktop-client/src/components/filters/FilterExpression.tsx +++ b/packages/desktop-client/src/components/filters/FilterExpression.tsx @@ -1,4 +1,5 @@ import React, { useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { mapField, friendlyOp } from 'loot-core/src/shared/rules'; import { integerToCurrency } from 'loot-core/src/shared/util'; @@ -38,6 +39,7 @@ export function FilterExpression<T extends RuleConditionEntity>({ onChange, onDelete, }: FilterExpressionProps<T>) { + const { t } = useTranslation(); const [editing, setEditing] = useState(false); const triggerRef = useRef(null); @@ -84,7 +86,7 @@ export function FilterExpression<T extends RuleConditionEntity>({ )} </div> </Button> - <Button type="bare" onClick={onDelete} aria-label="Delete filter"> + <Button type="bare" onClick={onDelete} aria-label={t('Delete filter')}> <SvgDelete style={{ width: 8, diff --git a/packages/desktop-client/src/components/filters/FilterMenu.tsx b/packages/desktop-client/src/components/filters/FilterMenu.tsx index b56649567ff2f31a3503166183eccdcc21bdcfd9..c3adb2048e8fade2b6a79e92384402ad9fa43b2b 100644 --- a/packages/desktop-client/src/components/filters/FilterMenu.tsx +++ b/packages/desktop-client/src/components/filters/FilterMenu.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { useTranslation } from 'react-i18next'; import { Menu } from '../common/Menu'; @@ -11,6 +12,8 @@ export function FilterMenu({ filterId: SavedFilter; onFilterMenuSelect: (item: string) => void; }) { + const { t } = useTranslation(); + return ( <Menu onMenuSelect={item => { @@ -19,29 +22,29 @@ export function FilterMenu({ items={ !filterId.id ? [ - { name: 'save-filter', text: 'Save new filter' }, - { name: 'clear-filter', text: 'Clear all conditions' }, + { name: 'save-filter', text: t('Save new filter') }, + { name: 'clear-filter', text: t('Clear all conditions') }, ] : filterId.id !== null && filterId.status === 'saved' ? [ - { name: 'rename-filter', text: 'Rename' }, - { name: 'delete-filter', text: 'Delete' }, + { name: 'rename-filter', text: t('Rename') }, + { name: 'delete-filter', text: t('Delete') }, Menu.line, { name: 'save-filter', - text: 'Save new filter', + text: t('Save new filter'), disabled: true, }, - { name: 'clear-filter', text: 'Clear all conditions' }, + { name: 'clear-filter', text: t('Clear all conditions') }, ] : [ - { name: 'rename-filter', text: 'Rename' }, - { name: 'update-filter', text: 'Update condtions' }, - { name: 'reload-filter', text: 'Revert changes' }, - { name: 'delete-filter', text: 'Delete' }, + { name: 'rename-filter', text: t('Rename') }, + { name: 'update-filter', text: t('Update condtions') }, + { name: 'reload-filter', text: t('Revert changes') }, + { name: 'delete-filter', text: t('Delete') }, Menu.line, - { name: 'save-filter', text: 'Save new filter' }, - { name: 'clear-filter', text: 'Clear all conditions' }, + { name: 'save-filter', text: t('Save new filter') }, + { name: 'clear-filter', text: t('Clear all conditions') }, ] } /> diff --git a/packages/desktop-client/src/components/filters/FiltersButton.tsx b/packages/desktop-client/src/components/filters/FiltersButton.tsx index 6d82904ee24698709bd76381ac63e865eb7248d9..35be2498683f859fa09dbd72bc958ceb84bb6589 100644 --- a/packages/desktop-client/src/components/filters/FiltersButton.tsx +++ b/packages/desktop-client/src/components/filters/FiltersButton.tsx @@ -1,11 +1,14 @@ import React from 'react'; +import { useTranslation } from 'react-i18next'; import { SvgFilter } from '../../icons/v1/Filter'; import { Button } from '../common/Button'; export function FiltersButton({ onClick }: { onClick: () => void }) { + const { t } = useTranslation(); + return ( - <Button type="bare" onClick={onClick} title="Filters"> + <Button type="bare" onClick={onClick} title={t('Filters')}> <SvgFilter style={{ width: 12, height: 12, marginRight: 5 }} /> Filter </Button> ); diff --git a/packages/desktop-client/src/components/filters/FiltersMenu.jsx b/packages/desktop-client/src/components/filters/FiltersMenu.jsx index fc971664ece2800f597d11a384d26f58a991b548..61720dff6dd019669b6b458d47abbd6add023676 100644 --- a/packages/desktop-client/src/components/filters/FiltersMenu.jsx +++ b/packages/desktop-client/src/components/filters/FiltersMenu.jsx @@ -1,5 +1,6 @@ import React, { useState, useRef, useEffect, useReducer } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; +import { Trans, useTranslation } from 'react-i18next'; import { FocusScope } from '@react-aria/focus'; import { @@ -62,6 +63,7 @@ function ConfigureField({ dispatch, onApply, }) { + const { t } = useTranslation(); const [subfield, setSubfield] = useState(initialSubfield); const inputRef = useRef(); const prevOp = useRef(null); @@ -91,15 +93,15 @@ function ConfigureField({ options={ field === 'amount' ? [ - ['amount', 'Amount'], - ['amount-inflow', 'Amount (inflow)'], - ['amount-outflow', 'Amount (outflow)'], + ['amount', t('Amount')], + ['amount-inflow', t('Amount (inflow)')], + ['amount-outflow', t('Amount (outflow)')], ] : field === 'date' ? [ - ['date', 'Date'], - ['month', 'Month'], - ['year', 'Year'], + ['date', t('Date')], + ['month', t('Month')], + ['year', t('Year')], ] : null } @@ -125,7 +127,7 @@ function ConfigureField({ marginBottom: 10, }} > - {field === 'saved' && 'Existing filters will be cleared'} + {field === 'saved' && t('Existing filters will be cleared')} </View> <Stack @@ -231,7 +233,7 @@ function ConfigureField({ }); }} > - Apply + <Trans>Apply</Trans> </Button> </Stack> </form> @@ -240,6 +242,7 @@ function ConfigureField({ } export function FilterButton({ onApply, compact, hover, exclude }) { + const { t } = useTranslation(); const filters = useFilters(); const triggerRef = useRef(null); @@ -285,7 +288,7 @@ export function FilterButton({ onApply, compact, hover, exclude }) { if (isDateValid(date)) { cond.value = formatDate(date, 'yyyy-MM'); } else { - alert('Invalid date format'); + alert(t('Invalid date format')); return; } } else if (cond.options.year) { @@ -293,7 +296,7 @@ export function FilterButton({ onApply, compact, hover, exclude }) { if (isDateValid(date)) { cond.value = formatDate(date, 'yyyy'); } else { - alert('Invalid date format'); + alert(t('Invalid date format')); return; } } @@ -329,7 +332,11 @@ export function FilterButton({ onApply, compact, hover, exclude }) { lineHeight: 1.5, padding: '6px 10px', }} - content={<Text>Filters</Text>} + content={ + <Text> + <Trans>Filters</Trans> + </Text> + } placement="bottom start" triggerProps={{ isDisabled: !hover, diff --git a/packages/desktop-client/src/components/filters/NameFilter.tsx b/packages/desktop-client/src/components/filters/NameFilter.tsx index 0e4285e85e50dfdd08f0b6188e8ccb1a03b398e9..b8ad19ac0fab46bc66799fbaddb8552831b27505 100644 --- a/packages/desktop-client/src/components/filters/NameFilter.tsx +++ b/packages/desktop-client/src/components/filters/NameFilter.tsx @@ -1,4 +1,5 @@ import React, { useRef, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { theme } from '../../style'; import { Button } from '../common/Button'; @@ -22,6 +23,7 @@ export function NameFilter({ onAddUpdate: () => void; err: string | null; }) { + const { t } = useTranslation(); const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { @@ -42,7 +44,7 @@ export function NameFilter({ > <FormField style={{ flex: 1 }}> <FormLabel - title="Filter Name" + title={t('Filter Name')} htmlFor="name-field" style={{ userSelect: 'none' }} /> @@ -61,7 +63,7 @@ export function NameFilter({ onAddUpdate(); }} > - {adding ? 'Add' : 'Update'} + {adding ? t('Add') : t('Update')} </Button> </Stack> </form> diff --git a/packages/desktop-client/src/components/filters/SavedFilterMenuButton.tsx b/packages/desktop-client/src/components/filters/SavedFilterMenuButton.tsx index ba5658f6b76fc3197624e8860e0e23f71b236709..1a2d68e525b6e5bc90f9269d56119de12d7aa1d7 100644 --- a/packages/desktop-client/src/components/filters/SavedFilterMenuButton.tsx +++ b/packages/desktop-client/src/components/filters/SavedFilterMenuButton.tsx @@ -1,4 +1,5 @@ import React, { useRef, useState } from 'react'; +import { Trans, useTranslation } from 'react-i18next'; import { send, sendCatch } from 'loot-core/src/platform/client/fetch'; import { type TransactionFilterEntity } from 'loot-core/types/models'; @@ -36,6 +37,7 @@ export function SavedFilterMenuButton({ onReloadSavedFilter: (savedFilter: SavedFilter, value?: string) => void; savedFilters: TransactionFilterEntity[]; }) { + const { t } = useTranslation(); const [nameOpen, setNameOpen] = useState(false); const [adding, setAdding] = useState(false); const [menuOpen, setMenuOpen] = useState(false); @@ -176,10 +178,12 @@ export function SavedFilterMenuButton({ flexShrink: 0, }} > - {!filterId.id ? 'Unsaved filter' : filterId.name} + {!filterId.id ? t('Unsaved filter') : filterId.name} </Text> {filterId.id && filterId.status !== 'saved' && ( - <Text>(modified) </Text> + <Text> + <Trans>(modified)</Trans> + </Text> )} <SvgExpandArrow width={8} height={8} style={{ marginRight: 5 }} /> </Button> diff --git a/upcoming-release-notes/3270.md b/upcoming-release-notes/3270.md new file mode 100644 index 0000000000000000000000000000000000000000..85a2c1b255e0383bad9267690cea26945c8129d5 --- /dev/null +++ b/upcoming-release-notes/3270.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [psybers] +--- + +Support translations in desktop-client/components/filters.