From ffaaf5270d69b425d8dca262a58c919d1f700e13 Mon Sep 17 00:00:00 2001 From: matalvernaz Date: Mon, 20 Apr 2026 09:03:34 -0700 Subject: [PATCH] New: Screen reader Accessibility Improvements --- .../src/Activity/Blocklist/BlocklistRow.tsx | 7 ++- frontend/src/Activity/History/HistoryRow.tsx | 7 ++- .../Queue/Details/QueueDetailsProvider.tsx | 2 +- frontend/src/Activity/Queue/QueueRow.tsx | 2 + .../AddNewSeries/AddNewSeriesSearchResult.tsx | 10 ++++- .../Filter/Builder/FilterBuilderRow.tsx | 8 +++- .../Filter/CustomFilters/CustomFilter.tsx | 6 ++- .../Components/Form/KeyValueListInputItem.tsx | 2 + .../src/Components/Form/Tag/TagInputTag.tsx | 2 + frontend/src/Components/Link/IconButton.tsx | 3 +- frontend/src/Components/Modal/Modal.tsx | 43 ++++++++++++------- frontend/src/Components/Modal/ModalContext.ts | 11 +++++ frontend/src/Components/Modal/ModalHeader.tsx | 10 ++++- .../src/Components/MonitorToggleButton.tsx | 1 + .../src/Components/Page/Header/PageHeader.tsx | 1 + .../Components/Page/Sidebar/PageSidebar.tsx | 5 ++- .../Page/Sidebar/PageSidebarItem.tsx | 3 +- frontend/src/Components/Table/Table.tsx | 6 ++- .../src/Components/Table/TableHeaderCell.tsx | 26 +++++++++-- frontend/src/Components/Table/TablePager.tsx | 16 +++++-- frontend/src/Episode/EpisodeSearchCell.tsx | 1 + .../src/Episode/History/EpisodeHistoryRow.tsx | 1 + .../src/Episode/Summary/EpisodeFileRow.tsx | 1 + .../Folder/FavoriteFolderRow.tsx | 1 + .../Folder/RecentFolderRow.tsx | 6 +++ frontend/src/RootFolder/RootFolderRow.tsx | 1 + frontend/src/Series/Details/SeriesDetails.tsx | 6 +++ .../Series/Details/SeriesDetailsSeason.tsx | 5 +++ .../src/Series/History/SeriesHistoryRow.tsx | 1 + .../Index/Overview/SeriesIndexOverview.tsx | 1 + .../Index/Posters/SeriesIndexPoster.tsx | 1 + .../src/Series/Index/Table/SeriesIndexRow.tsx | 1 + .../Index/Table/SeriesIndexTableHeader.tsx | 6 ++- .../CustomFormats/CustomFormat.tsx | 2 + .../Manage/ManageCustomFormatsModalRow.tsx | 1 + .../Specifications/Specification.tsx | 1 + .../ImportListExclusionRow.tsx | 1 + .../ImportListExclusions.tsx | 1 + .../ImportLists/ImportLists/ImportList.tsx | 1 + .../Settings/Indexers/Indexers/Indexer.tsx | 1 + .../Profiles/Quality/QualityProfile.tsx | 1 + .../Profiles/Quality/QualityProfileItem.tsx | 1 + .../Quality/QualityProfileItemGroup.tsx | 1 + .../Settings/Tags/AutoTagging/AutoTagging.tsx | 1 + .../Specifications/Specification.tsx | 1 + frontend/src/System/Backup/BackupRow.tsx | 2 + frontend/src/System/Status/Health/Health.tsx | 1 + .../System/Status/Health/HealthItemLink.tsx | 5 +++ .../src/System/Tasks/Queued/QueuedTaskRow.tsx | 1 + .../Tasks/Scheduled/ScheduledTaskRow.tsx | 2 + src/NzbDrone.Core/Localization/Core/en.json | 9 ++++ 51 files changed, 199 insertions(+), 37 deletions(-) create mode 100644 frontend/src/Components/Modal/ModalContext.ts diff --git a/frontend/src/Activity/Blocklist/BlocklistRow.tsx b/frontend/src/Activity/Blocklist/BlocklistRow.tsx index cb6a6ffb9..3595203ef 100644 --- a/frontend/src/Activity/Blocklist/BlocklistRow.tsx +++ b/frontend/src/Activity/Blocklist/BlocklistRow.tsx @@ -137,10 +137,15 @@ function BlocklistRow({ if (name === 'actions') { return ( - + - + ); } diff --git a/frontend/src/Activity/Queue/Details/QueueDetailsProvider.tsx b/frontend/src/Activity/Queue/Details/QueueDetailsProvider.tsx index 05d1b8235..ef6c50ab1 100644 --- a/frontend/src/Activity/Queue/Details/QueueDetailsProvider.tsx +++ b/frontend/src/Activity/Queue/Details/QueueDetailsProvider.tsx @@ -46,7 +46,7 @@ export function useQueueItemForEpisode(episodeId: number) { const queue = useContext(QueueDetailsContext); return useMemo(() => { - return queue?.find((item) => item.episodeIds.includes(episodeId)); + return queue?.find((item) => item.episodeIds?.includes(episodeId)); }, [episodeId, queue]); } diff --git a/frontend/src/Activity/Queue/QueueRow.tsx b/frontend/src/Activity/Queue/QueueRow.tsx index 2cc69d690..a23c8af2a 100644 --- a/frontend/src/Activity/Queue/QueueRow.tsx +++ b/frontend/src/Activity/Queue/QueueRow.tsx @@ -369,6 +369,7 @@ function QueueRow(props: QueueRowProps) { {showInteractiveImport ? ( ) : null} @@ -377,6 +378,7 @@ function QueueRow(props: QueueRowProps) { diff --git a/frontend/src/AddSeries/AddNewSeries/AddNewSeriesSearchResult.tsx b/frontend/src/AddSeries/AddNewSeries/AddNewSeriesSearchResult.tsx index 76c8669fe..877cd2f25 100644 --- a/frontend/src/AddSeries/AddNewSeries/AddNewSeriesSearchResult.tsx +++ b/frontend/src/AddSeries/AddNewSeries/AddNewSeriesSearchResult.tsx @@ -65,7 +65,13 @@ function AddNewSeriesSearchResult({ series }: AddNewSeriesSearchResultProps) { return (
- +
{isSmallScreen ? null : ( @@ -113,12 +119,14 @@ function AddNewSeriesSearchResult({ series }: AddNewSeriesSearchResultProps) {
diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRow.tsx b/frontend/src/Components/Filter/Builder/FilterBuilderRow.tsx index 0ccc3070d..00aa58936 100644 --- a/frontend/src/Components/Filter/Builder/FilterBuilderRow.tsx +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRow.tsx @@ -10,6 +10,7 @@ import { import { DateFilterValue, FilterType } from 'Helpers/Props/filterTypes'; import { InputChanged } from 'typings/inputs'; import sortByProp from 'Utilities/Array/sortByProp'; +import translate from 'Utilities/String/translate'; import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue'; import DateFilterBuilderRowValue from './DateFilterBuilderRowValue'; import DefaultFilterBuilderRowValue from './DefaultFilterBuilderRowValue'; @@ -300,11 +301,16 @@ function FilterBuilderRow({
- +
); diff --git a/frontend/src/Components/Filter/CustomFilters/CustomFilter.tsx b/frontend/src/Components/Filter/CustomFilters/CustomFilter.tsx index c01686381..dcc7e6405 100644 --- a/frontend/src/Components/Filter/CustomFilters/CustomFilter.tsx +++ b/frontend/src/Components/Filter/CustomFilters/CustomFilter.tsx @@ -59,7 +59,11 @@ function CustomFilter({
{label}
- + diff --git a/frontend/src/Components/Form/Tag/TagInputTag.tsx b/frontend/src/Components/Form/Tag/TagInputTag.tsx index 7b549767c..3612258dc 100644 --- a/frontend/src/Components/Form/Tag/TagInputTag.tsx +++ b/frontend/src/Components/Form/Tag/TagInputTag.tsx @@ -4,6 +4,7 @@ import IconButton from 'Components/Link/IconButton'; import Link from 'Components/Link/Link'; import MiddleTruncate from 'Components/MiddleTruncate'; import { icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import { TagBase } from './TagInput'; import styles from './TagInputTag.css'; @@ -66,6 +67,7 @@ function TagInputTag({ diff --git a/frontend/src/Components/Link/IconButton.tsx b/frontend/src/Components/Link/IconButton.tsx index b6951c00c..52ac0b036 100644 --- a/frontend/src/Components/Link/IconButton.tsx +++ b/frontend/src/Components/Link/IconButton.tsx @@ -1,7 +1,6 @@ import classNames from 'classnames'; import React from 'react'; import Icon, { IconProps } from 'Components/Icon'; -import translate from 'Utilities/String/translate'; import Link, { LinkProps } from './Link'; import styles from './IconButton.css'; @@ -26,7 +25,6 @@ export default function IconButton({ className, otherProps.isDisabled && styles.isDisabled )} - aria-label={translate('TableOptionsButton')} {...otherProps} > ); diff --git a/frontend/src/Components/Modal/Modal.tsx b/frontend/src/Components/Modal/Modal.tsx index cfc157f93..e3b54beb6 100644 --- a/frontend/src/Components/Modal/Modal.tsx +++ b/frontend/src/Components/Modal/Modal.tsx @@ -15,6 +15,7 @@ import { Size } from 'Helpers/Props/sizes'; import { isIOS } from 'Utilities/browser'; import * as keyCodes from 'Utilities/Constants/keyCodes'; import { setScrollLock } from 'Utilities/scrollLock'; +import { ModalContext } from './ModalContext'; import ModalError from './ModalError'; import styles from './Modal.css'; @@ -163,26 +164,36 @@ function Modal({ return null; } + const headerId = `${modalId}-header`; + return ReactDOM.createPortal( - -
-
-
- + +
+
+
- {children} - + + {children} + +
-
- , + + , node! ); } diff --git a/frontend/src/Components/Modal/ModalContext.ts b/frontend/src/Components/Modal/ModalContext.ts new file mode 100644 index 000000000..405d5ddd1 --- /dev/null +++ b/frontend/src/Components/Modal/ModalContext.ts @@ -0,0 +1,11 @@ +import { createContext, useContext } from 'react'; + +interface ModalContextValue { + headerId: string; +} + +export const ModalContext = createContext({ headerId: '' }); + +export function useModalContext() { + return useContext(ModalContext); +} diff --git a/frontend/src/Components/Modal/ModalHeader.tsx b/frontend/src/Components/Modal/ModalHeader.tsx index 86f2c9ac1..e90ad2f0b 100644 --- a/frontend/src/Components/Modal/ModalHeader.tsx +++ b/frontend/src/Components/Modal/ModalHeader.tsx @@ -1,4 +1,5 @@ import React, { ForwardedRef, forwardRef, ReactNode } from 'react'; +import { useModalContext } from './ModalContext'; import styles from './ModalHeader.css'; interface ModalHeaderProps extends React.HTMLAttributes { @@ -10,8 +11,15 @@ const ModalHeader = forwardRef( { children, ...otherProps }: ModalHeaderProps, ref: ForwardedRef ) => { + const { headerId } = useModalContext(); + return ( -
+
{children}
); diff --git a/frontend/src/Components/MonitorToggleButton.tsx b/frontend/src/Components/MonitorToggleButton.tsx index 1c1fcbbeb..36d95903f 100644 --- a/frontend/src/Components/MonitorToggleButton.tsx +++ b/frontend/src/Components/MonitorToggleButton.tsx @@ -54,6 +54,7 @@ function MonitorToggleButton(props: MonitorToggleButtonProps) { name={iconName} size={size} title={title} + aria-label={title} isDisabled={isDisabled} isSpinning={isSaving} {...otherProps} diff --git a/frontend/src/Components/Page/Header/PageHeader.tsx b/frontend/src/Components/Page/Header/PageHeader.tsx index c63447bbf..54a96697c 100644 --- a/frontend/src/Components/Page/Header/PageHeader.tsx +++ b/frontend/src/Components/Page/Header/PageHeader.tsx @@ -55,6 +55,7 @@ function PageHeader() {
diff --git a/frontend/src/Components/Page/Sidebar/PageSidebar.tsx b/frontend/src/Components/Page/Sidebar/PageSidebar.tsx index e2f5460f9..a2245daee 100644 --- a/frontend/src/Components/Page/Sidebar/PageSidebar.tsx +++ b/frontend/src/Components/Page/Sidebar/PageSidebar.tsx @@ -435,10 +435,11 @@ function PageSidebar() { const ScrollerComponent = isSmallScreen ? Scroller : OverlayScroller; return ( -
{isSmallScreen ? (
@@ -521,7 +522,7 @@ function PageSidebar() { -
+ ); } diff --git a/frontend/src/Components/Page/Sidebar/PageSidebarItem.tsx b/frontend/src/Components/Page/Sidebar/PageSidebarItem.tsx index 37d9bafa0..c2b8cfff1 100644 --- a/frontend/src/Components/Page/Sidebar/PageSidebarItem.tsx +++ b/frontend/src/Components/Page/Sidebar/PageSidebarItem.tsx @@ -46,11 +46,12 @@ function PageSidebarItem({ isActive && styles.isActiveLink )} to={to} + aria-current={isActive ? 'page' : undefined} onPress={handlePress} > {!!iconName && ( - + )} diff --git a/frontend/src/Components/Table/Table.tsx b/frontend/src/Components/Table/Table.tsx index c72b68b96..995529ec2 100644 --- a/frontend/src/Components/Table/Table.tsx +++ b/frontend/src/Components/Table/Table.tsx @@ -7,6 +7,7 @@ import { icons, scrollDirections } from 'Helpers/Props'; import { SortDirection } from 'Helpers/Props/sortDirections'; import { CheckInputChanged } from 'typings/inputs'; import { TableOptionsChangePayload } from 'typings/Table'; +import translate from 'Utilities/String/translate'; import Column from './Column'; import TableHeader from './TableHeader'; import TableHeaderCell from './TableHeaderCell'; @@ -94,7 +95,10 @@ function Table({ canModifyColumns={canModifyColumns} onTableOptionChange={onTableOptionChange} > - + ); diff --git a/frontend/src/Components/Table/TableHeaderCell.tsx b/frontend/src/Components/Table/TableHeaderCell.tsx index 13b8cf0f7..9311a81a5 100644 --- a/frontend/src/Components/Table/TableHeaderCell.tsx +++ b/frontend/src/Components/Table/TableHeaderCell.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import Icon from 'Components/Icon'; import Link from 'Components/Link/Link'; import { icons, sortDirections } from 'Helpers/Props'; @@ -41,6 +41,20 @@ function TableHeaderCell({ ? icons.SORT_ASCENDING : icons.SORT_DESCENDING; + const ariaSortValue = useMemo(() => { + if (!isSortable) { + return undefined; + } + + if (!isSorting) { + return 'none'; + } + + return sortDirection === sortDirections.ASCENDING + ? 'ascending' + : 'descending'; + }, [isSorting, sortDirection, isSortable]); + const handlePress = useCallback(() => { if (fixedSortDirection) { onSortPress?.(name, fixedSortDirection); @@ -56,14 +70,20 @@ function TableHeaderCell({ className={className} // label={typeof label === 'function' ? label() : label} title={typeof columnLabel === 'function' ? columnLabel() : columnLabel} + scope="col" + aria-sort={ariaSortValue} onPress={handlePress} > {children} - {isSorting && } + {isSorting ? ( + + ) : null} ) : ( - {children} + + {children} + ); } diff --git a/frontend/src/Components/Table/TablePager.tsx b/frontend/src/Components/Table/TablePager.tsx index 411b111bf..5394ccc69 100644 --- a/frontend/src/Components/Table/TablePager.tsx +++ b/frontend/src/Components/Table/TablePager.tsx @@ -108,9 +108,10 @@ function TablePager({ isFirstPage && styles.disabledPageButton )} isDisabled={isFirstPage} + aria-label={translate('PagerGoToFirstPage')} onPress={handleFirstPagePress} > - + - +
{isShowingPageSelect ? null : ( {page} / {totalPages} @@ -153,9 +159,10 @@ function TablePager({ isLastPage && styles.disabledPageButton )} isDisabled={isLastPage} + aria-label={translate('PagerGoToNextPage')} onPress={onNextPagePress} > - + - +
diff --git a/frontend/src/Episode/EpisodeSearchCell.tsx b/frontend/src/Episode/EpisodeSearchCell.tsx index 7e0f38a86..cea39a6ee 100644 --- a/frontend/src/Episode/EpisodeSearchCell.tsx +++ b/frontend/src/Episode/EpisodeSearchCell.tsx @@ -54,6 +54,7 @@ function EpisodeSearchCell({ diff --git a/frontend/src/Episode/History/EpisodeHistoryRow.tsx b/frontend/src/Episode/History/EpisodeHistoryRow.tsx index a5c4a14f5..1503fdccb 100644 --- a/frontend/src/Episode/History/EpisodeHistoryRow.tsx +++ b/frontend/src/Episode/History/EpisodeHistoryRow.tsx @@ -128,6 +128,7 @@ function EpisodeHistoryRow({ {eventType === 'grabbed' && ( diff --git a/frontend/src/InteractiveImport/Folder/FavoriteFolderRow.tsx b/frontend/src/InteractiveImport/Folder/FavoriteFolderRow.tsx index 7f1b3d393..b72a5faf7 100644 --- a/frontend/src/InteractiveImport/Folder/FavoriteFolderRow.tsx +++ b/frontend/src/InteractiveImport/Folder/FavoriteFolderRow.tsx @@ -33,6 +33,7 @@ function FavoriteFolderRow({ folder, onPress }: FavoriteFolderRowProps) { diff --git a/frontend/src/RootFolder/RootFolderRow.tsx b/frontend/src/RootFolder/RootFolderRow.tsx index 3d8c32b3a..2a2008a7c 100644 --- a/frontend/src/RootFolder/RootFolderRow.tsx +++ b/frontend/src/RootFolder/RootFolderRow.tsx @@ -83,6 +83,7 @@ function RootFolderRow(props: RootFolderRowProps) { diff --git a/frontend/src/Series/Details/SeriesDetails.tsx b/frontend/src/Series/Details/SeriesDetails.tsx index 605710b5f..0284d7d9c 100644 --- a/frontend/src/Series/Details/SeriesDetails.tsx +++ b/frontend/src/Series/Details/SeriesDetails.tsx @@ -574,6 +574,9 @@ function SeriesDetails({ seriesId }: SeriesDetailsProps) { title={translate('SeriesDetailsGoTo', { title: previousSeries.title, })} + aria-label={translate('SeriesDetailsGoTo', { + title: previousSeries.title, + })} to={`/series/${previousSeries.titleSlug}`} /> ) : null} @@ -586,6 +589,9 @@ function SeriesDetails({ seriesId }: SeriesDetailsProps) { title={translate('SeriesDetailsGoTo', { title: nextSeries.title, })} + aria-label={translate('SeriesDetailsGoTo', { + title: nextSeries.title, + })} to={`/series/${nextSeries.titleSlug}`} /> ) : null} diff --git a/frontend/src/Series/Details/SeriesDetailsSeason.tsx b/frontend/src/Series/Details/SeriesDetailsSeason.tsx index d48c54b03..b8d35de02 100644 --- a/frontend/src/Series/Details/SeriesDetailsSeason.tsx +++ b/frontend/src/Series/Details/SeriesDetailsSeason.tsx @@ -432,6 +432,7 @@ function SeriesDetailsSeason({ className={styles.actionButton} name={icons.INTERACTIVE} title={translate('InteractiveSearchSeason')} + aria-label={translate('InteractiveSearchSeason')} size={24} isDisabled={!totalEpisodeCount} onPress={handleInteractiveSearchPress} @@ -441,6 +442,7 @@ function SeriesDetailsSeason({ className={styles.actionButton} name={icons.ORGANIZE} title={translate('PreviewRenameSeason')} + aria-label={translate('PreviewRenameSeason')} size={24} isDisabled={!episodeFileCount} onPress={handleOrganizePress} @@ -450,6 +452,7 @@ function SeriesDetailsSeason({ className={styles.actionButton} name={icons.EPISODE_FILE} title={translate('ManageEpisodesSeason')} + aria-label={translate('ManageEpisodesSeason')} size={24} isDisabled={!episodeFileCount} onPress={handleManageEpisodesPress} @@ -459,6 +462,7 @@ function SeriesDetailsSeason({ className={styles.actionButton} name={icons.HISTORY} title={translate('HistorySeason')} + aria-label={translate('HistorySeason')} size={24} isDisabled={!totalEpisodeCount} onPress={handleHistoryPress} @@ -506,6 +510,7 @@ function SeriesDetailsSeason({ name={icons.COLLAPSE} size={20} title={translate('HideEpisodes')} + aria-label={translate('HideEpisodes')} onPress={handleExpandPress} />
diff --git a/frontend/src/Series/History/SeriesHistoryRow.tsx b/frontend/src/Series/History/SeriesHistoryRow.tsx index c1d82ae26..8968f234d 100644 --- a/frontend/src/Series/History/SeriesHistoryRow.tsx +++ b/frontend/src/Series/History/SeriesHistoryRow.tsx @@ -158,6 +158,7 @@ function SeriesHistoryRow({ {eventType === 'grabbed' ? (
diff --git a/frontend/src/Series/Index/Posters/SeriesIndexPoster.tsx b/frontend/src/Series/Index/Posters/SeriesIndexPoster.tsx index bd2c33593..03c9f98f6 100644 --- a/frontend/src/Series/Index/Posters/SeriesIndexPoster.tsx +++ b/frontend/src/Series/Index/Posters/SeriesIndexPoster.tsx @@ -162,6 +162,7 @@ function SeriesIndexPoster(props: SeriesIndexPosterProps) { className={styles.action} name={icons.EDIT} title={translate('EditSeries')} + aria-label={translate('EditSeries')} tabIndex={-1} onPress={onEditSeriesPress} /> diff --git a/frontend/src/Series/Index/Table/SeriesIndexRow.tsx b/frontend/src/Series/Index/Table/SeriesIndexRow.tsx index afea5d1af..18fbbb00d 100644 --- a/frontend/src/Series/Index/Table/SeriesIndexRow.tsx +++ b/frontend/src/Series/Index/Table/SeriesIndexRow.tsx @@ -490,6 +490,7 @@ function SeriesIndexRow(props: SeriesIndexRowProps) { diff --git a/frontend/src/Series/Index/Table/SeriesIndexTableHeader.tsx b/frontend/src/Series/Index/Table/SeriesIndexTableHeader.tsx index fcf80c73e..63b9dcf0e 100644 --- a/frontend/src/Series/Index/Table/SeriesIndexTableHeader.tsx +++ b/frontend/src/Series/Index/Table/SeriesIndexTableHeader.tsx @@ -16,6 +16,7 @@ import { } from 'Series/seriesOptionsStore'; import { CheckInputChanged } from 'typings/inputs'; import { TableOptionsChangePayload } from 'typings/Table'; +import translate from 'Utilities/String/translate'; import hasGrowableColumns from './hasGrowableColumns'; import SeriesIndexTableOptions from './SeriesIndexTableOptions'; import styles from './SeriesIndexTableHeader.css'; @@ -95,7 +96,10 @@ function SeriesIndexTableHeader(props: SeriesIndexTableHeaderProps) { optionsComponent={SeriesIndexTableOptions} onTableOptionChange={onTableOptionChange} > - + ); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.tsx b/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.tsx index 335a7a555..922951280 100644 --- a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.tsx +++ b/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.tsx @@ -83,6 +83,7 @@ function CustomFormat({ @@ -90,6 +91,7 @@ function CustomFormat({ diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Manage/ManageCustomFormatsModalRow.tsx b/frontend/src/Settings/CustomFormats/CustomFormats/Manage/ManageCustomFormatsModalRow.tsx index cfcd461a9..03891dd69 100644 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Manage/ManageCustomFormatsModalRow.tsx +++ b/frontend/src/Settings/CustomFormats/CustomFormats/Manage/ManageCustomFormatsModalRow.tsx @@ -94,6 +94,7 @@ function ManageCustomFormatsModalRow({ diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.tsx b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.tsx index afb91aa97..5d05ccafd 100644 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.tsx +++ b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.tsx @@ -73,6 +73,7 @@ function Specification({ diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.tsx b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.tsx index 6e09c917c..065d0cad9 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.tsx +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusionRow.tsx @@ -77,6 +77,7 @@ function ImportListExclusionRow({ diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.tsx b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.tsx index 954cf8b7f..37ae61cd7 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.tsx +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.tsx @@ -199,6 +199,7 @@ function ImportListExclusionsContent() { diff --git a/frontend/src/Settings/ImportLists/ImportLists/ImportList.tsx b/frontend/src/Settings/ImportLists/ImportLists/ImportList.tsx index d5ebf4fa9..6613428b5 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/ImportList.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/ImportList.tsx @@ -76,6 +76,7 @@ function ImportList({ diff --git a/frontend/src/Settings/Indexers/Indexers/Indexer.tsx b/frontend/src/Settings/Indexers/Indexers/Indexer.tsx index 6100e047f..f3da6fa9b 100644 --- a/frontend/src/Settings/Indexers/Indexers/Indexer.tsx +++ b/frontend/src/Settings/Indexers/Indexers/Indexer.tsx @@ -75,6 +75,7 @@ function Indexer({ diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfile.tsx b/frontend/src/Settings/Profiles/Quality/QualityProfile.tsx index 36e0d6b02..14a70d16c 100644 --- a/frontend/src/Settings/Profiles/Quality/QualityProfile.tsx +++ b/frontend/src/Settings/Profiles/Quality/QualityProfile.tsx @@ -76,6 +76,7 @@ function QualityProfile({ diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.tsx b/frontend/src/Settings/Profiles/Quality/QualityProfileItem.tsx index 09a363ded..da24aecf5 100644 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.tsx +++ b/frontend/src/Settings/Profiles/Quality/QualityProfileItem.tsx @@ -75,6 +75,7 @@ function QualityProfileItem({ className={styles.createGroupButton} name={icons.GROUP} title={translate('Group')} + aria-label={translate('Group')} onPress={handleCreateGroupPress} /> )} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.tsx b/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.tsx index 06a840a2c..801728802 100644 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.tsx +++ b/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.tsx @@ -89,6 +89,7 @@ function QualityProfileItemGroup({ className={styles.deleteGroupButton} name={icons.UNGROUP} title={translate('Ungroup')} + aria-label={translate('Ungroup')} onPress={handleDeleteGroupPress} /> diff --git a/frontend/src/Settings/Tags/AutoTagging/AutoTagging.tsx b/frontend/src/Settings/Tags/AutoTagging/AutoTagging.tsx index a53654897..8f1179188 100644 --- a/frontend/src/Settings/Tags/AutoTagging/AutoTagging.tsx +++ b/frontend/src/Settings/Tags/AutoTagging/AutoTagging.tsx @@ -74,6 +74,7 @@ export default function AutoTagging({ diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.tsx b/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.tsx index 099dfd5d8..b49bf27c6 100644 --- a/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.tsx +++ b/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.tsx @@ -70,6 +70,7 @@ export default function Specification({ diff --git a/frontend/src/System/Backup/BackupRow.tsx b/frontend/src/System/Backup/BackupRow.tsx index 739d07ec9..4b2d682eb 100644 --- a/frontend/src/System/Backup/BackupRow.tsx +++ b/frontend/src/System/Backup/BackupRow.tsx @@ -96,12 +96,14 @@ function BackupRow({ id, type, name, path, size, time }: BackupRowProps) { diff --git a/frontend/src/System/Status/Health/Health.tsx b/frontend/src/System/Status/Health/Health.tsx index fc334b542..07ed81c24 100644 --- a/frontend/src/System/Status/Health/Health.tsx +++ b/frontend/src/System/Status/Health/Health.tsx @@ -118,6 +118,7 @@ function Health() { name={icons.WIKI} to={item.wikiUrl} title={translate('ReadTheWikiForMoreInformation')} + aria-label={translate('ReadTheWikiForMoreInformation')} /> diff --git a/frontend/src/System/Status/Health/HealthItemLink.tsx b/frontend/src/System/Status/Health/HealthItemLink.tsx index ac3bafade..90a9b4c3a 100644 --- a/frontend/src/System/Status/Health/HealthItemLink.tsx +++ b/frontend/src/System/Status/Health/HealthItemLink.tsx @@ -20,6 +20,7 @@ function HealthItemLink(props: HealthItemLinkProps) { ); @@ -30,6 +31,7 @@ function HealthItemLink(props: HealthItemLinkProps) { ); @@ -38,6 +40,7 @@ function HealthItemLink(props: HealthItemLinkProps) { ); @@ -46,6 +49,7 @@ function HealthItemLink(props: HealthItemLinkProps) { ); @@ -54,6 +58,7 @@ function HealthItemLink(props: HealthItemLinkProps) { ); diff --git a/frontend/src/System/Tasks/Queued/QueuedTaskRow.tsx b/frontend/src/System/Tasks/Queued/QueuedTaskRow.tsx index 7b426edbf..0f15dde9f 100644 --- a/frontend/src/System/Tasks/Queued/QueuedTaskRow.tsx +++ b/frontend/src/System/Tasks/Queued/QueuedTaskRow.tsx @@ -219,6 +219,7 @@ export default function QueuedTaskRow(props: QueuedTaskRowProps) { {status === 'queued' && ( diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.tsx b/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.tsx index c4e5035ea..ce446fb14 100644 --- a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.tsx +++ b/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.tsx @@ -10,6 +10,7 @@ import { isCommandExecuting } from 'Utilities/Command'; import formatDate from 'Utilities/Date/formatDate'; import formatDateTime from 'Utilities/Date/formatDateTime'; import formatTimeSpan from 'Utilities/Date/formatTimeSpan'; +import translate from 'Utilities/String/translate'; import styles from './ScheduledTaskRow.css'; interface ScheduledTaskRowProps { @@ -138,6 +139,7 @@ function ScheduledTaskRow({ diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index db9577107..51d7e3c78 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -57,6 +57,7 @@ "AddedDate": "Added: {date}", "AddedToDownloadQueue": "Added to download queue", "AddingTag": "Adding tag", + "AdvancedSettings": "Advanced Settings", "AfterManualRefresh": "After Manual Refresh", "Age": "Age", "AgeWhenGrabbed": "Age (when grabbed)", @@ -1182,6 +1183,7 @@ "Logs": "Logs", "LongDateFormat": "Long Date Format", "Lowercase": "Lowercase", + "MainNavigation": "Main Navigation", "MaintenanceRelease": "Maintenance Release: bug fixes and other improvements. See Github Commit History for more details", "ManageClients": "Manage Clients", "ManageCustomFormats": "Manage Custom Formats", @@ -1635,6 +1637,11 @@ "OverviewOptions": "Overview Options", "PackageVersion": "Package Version", "PackageVersionInfo": "{packageVersion} by {packageAuthor}", + "PagerGoToFirstPage": "Go to first page", + "PagerGoToLastPage": "Go to last page", + "PagerGoToNextPage": "Go to next page", + "PagerGoToPage": "Go to page {page} of {totalPages}", + "PagerGoToPreviousPage": "Go to previous page", "Parse": "Parse", "ParseModalErrorParsing": "Error parsing, please try again.", "ParseModalHelpText": "Enter a release title in the input above", @@ -1875,6 +1882,7 @@ "RssSyncInterval": "RSS Sync Interval", "RssSyncIntervalHelpText": "Interval in minutes. Set to zero to disable (this will stop all automatic release grabbing)", "RssSyncIntervalHelpTextWarning": "This will apply to all indexers, please follow the rules set forth by them", + "Run": "Run", "Runtime": "Runtime", "Saturday": "Saturday", "Save": "Save", @@ -2232,6 +2240,7 @@ "VideoCodec": "Video Codec", "VideoDynamicRange": "Video Dynamic Range", "View": "View", + "ViewSeriesOnTvdb": "View {title} on TVDB", "VisitTheWikiForMoreDetails": "Visit the wiki for more details: ", "WaitingToImport": "Waiting to Import", "WaitingToProcess": "Waiting to Process",