From ea4b566aff30c9de9bdcd0188b9b27211f253170 Mon Sep 17 00:00:00 2001 From: Caleb Cox Date: Wed, 13 Nov 2024 11:31:52 -0600 Subject: [PATCH] Localize all data grid and pagination labels --- .../DonationTable/DonationTable.tsx | 11 +- .../AccountTransactionTable.tsx | 11 +- .../PartnerGivingAnalysisReport.tsx | 8 +- src/hooks/useMuiLocaleText.ts | 225 ++++++++++++++++++ 4 files changed, 237 insertions(+), 18 deletions(-) create mode 100644 src/hooks/useMuiLocaleText.ts diff --git a/src/components/DonationTable/DonationTable.tsx b/src/components/DonationTable/DonationTable.tsx index adc369cbb..7cee9c88b 100644 --- a/src/components/DonationTable/DonationTable.tsx +++ b/src/components/DonationTable/DonationTable.tsx @@ -27,6 +27,7 @@ import { useTranslation } from 'react-i18next'; import { useFetchAllPages } from 'src/hooks/useFetchAllPages'; import { useLocalStorage } from 'src/hooks/useLocalStorage'; import { useLocale } from 'src/hooks/useLocale'; +import { useDataGridLocaleText } from 'src/hooks/useMuiLocaleText'; import { currencyFormat, dateFormatShort } from 'src/lib/intlFormat'; import { DynamicEditDonationModal, @@ -362,6 +363,8 @@ export const DonationTable: React.FC = ({ }, ); + const localeText = useDataGridLocaleText(); + return ( <> {data?.donations.nodes.length ? ( @@ -384,13 +387,7 @@ export const DonationTable: React.FC = ({ autoHeight disableSelectionOnClick disableVirtualization - localeText={{ - MuiTablePagination: { - labelRowsPerPage: t('Rows per page:'), - labelDisplayedRows: ({ from, to, count }) => - t('{{from}}-{{to}} of {{total}}', { from, to, total: count }), - }, - }} + localeText={localeText} /> {data.donations.pageInfo.hasNextPage ? ( diff --git a/src/components/Reports/FinancialAccountsReport/AccountTransactions/AccountTransactionTable/AccountTransactionTable.tsx b/src/components/Reports/FinancialAccountsReport/AccountTransactions/AccountTransactionTable/AccountTransactionTable.tsx index 7045ef2a7..c715897b8 100644 --- a/src/components/Reports/FinancialAccountsReport/AccountTransactions/AccountTransactionTable/AccountTransactionTable.tsx +++ b/src/components/Reports/FinancialAccountsReport/AccountTransactions/AccountTransactionTable/AccountTransactionTable.tsx @@ -13,6 +13,7 @@ import { DateTime } from 'luxon'; import { useTranslation } from 'react-i18next'; import { Maybe } from 'src/graphql/types.generated'; import { useLocale } from 'src/hooks/useLocale'; +import { useDataGridLocaleText } from 'src/hooks/useMuiLocaleText'; import { currencyFormat, dateFormatShort } from 'src/lib/intlFormat'; import { FinancialAccountContext, @@ -290,6 +291,8 @@ export const AccountTransactionTable: React.FC = ({ }, ]; + const localeText = useDataGridLocaleText(); + return ( <> = ({ rowHeight={70} autoHeight getRowHeight={() => 'auto'} - localeText={{ - MuiTablePagination: { - labelRowsPerPage: t('Rows per page:'), - labelDisplayedRows: ({ from, to, count }) => - t('{{from}}-{{to}} of {{total}}', { from, to, total: count }), - }, - }} + localeText={localeText} /> diff --git a/src/components/Reports/PartnerGivingAnalysisReport/PartnerGivingAnalysisReport.tsx b/src/components/Reports/PartnerGivingAnalysisReport/PartnerGivingAnalysisReport.tsx index eef597949..136883f8f 100644 --- a/src/components/Reports/PartnerGivingAnalysisReport/PartnerGivingAnalysisReport.tsx +++ b/src/components/Reports/PartnerGivingAnalysisReport/PartnerGivingAnalysisReport.tsx @@ -21,6 +21,7 @@ import { import { useGetPartnerGivingAnalysisIdsForMassSelectionQuery } from 'src/hooks/GetIdsForMassSelection.generated'; import { useDebouncedValue } from 'src/hooks/useDebounce'; import { useMassSelection } from 'src/hooks/useMassSelection'; +import { useTablePaginationLocaleText } from 'src/hooks/useMuiLocaleText'; import { sanitizeFilters } from 'src/lib/sanitizeFilters'; import { useGetPartnerGivingAnalysisReportQuery } from './PartnerGivingAnalysisReport.generated'; import { PartnerGivingAnalysisReportTable as Table } from './Table/Table'; @@ -142,6 +143,8 @@ export const PartnerGivingAnalysisReport = forwardRef< isRowChecked, } = useMassSelection(allContactIds); + const localeText = useTablePaginationLocaleText(); + const handleRequestSort = ( event: React.MouseEvent, property: string, @@ -216,16 +219,13 @@ export const PartnerGivingAnalysisReport = forwardRef< page={page} rowsPerPage={limit} rowsPerPageOptions={[10, 25, 50]} - labelRowsPerPage={t('Rows per page:')} - labelDisplayedRows={({ from, to, count }) => - t('{{from}}-{{to}} of {{total}}', { from, to, total: count }) - } SelectProps={{ inputProps: { 'aria-label': t('rows per page'), }, native: true, }} + {...localeText} /> ) : ( diff --git a/src/hooks/useMuiLocaleText.ts b/src/hooks/useMuiLocaleText.ts new file mode 100644 index 000000000..386d54b0d --- /dev/null +++ b/src/hooks/useMuiLocaleText.ts @@ -0,0 +1,225 @@ +import { useMemo } from 'react'; +import { TablePaginationProps } from '@mui/material'; +import { GridLocaleText } from '@mui/x-data-grid'; +import { useTranslation } from 'react-i18next'; +import { useLocale } from './useLocale'; + +export const useDataGridLocaleText = (): GridLocaleText => { + const { t } = useTranslation(); + const locale = useLocale(); + const tablePaginationLocaleText = useTablePaginationLocaleText(); + + return useMemo( + () => ({ + // Root + noRowsLabel: t('No rows'), + + noResultsOverlayLabel: t('No results found.'), + errorOverlayDefaultLabel: t('An error occurred.'), + + // Density selector toolbar button text + toolbarDensity: t('Density'), + + toolbarDensityLabel: t('Density'), + toolbarDensityCompact: t('Compact'), + toolbarDensityStandard: t('Standard'), + toolbarDensityComfortable: t('Comfortable'), + + // Columns selector toolbar button text + toolbarColumns: t('Columns'), + + toolbarColumnsLabel: t('Select columns'), + + // Filters toolbar button text + toolbarFilters: t('Filters'), + + toolbarFiltersLabel: t('Show filters'), + toolbarFiltersTooltipHide: t('Hide filters'), + toolbarFiltersTooltipShow: t('Show filters'), + + toolbarFiltersTooltipActive: (count) => + count !== 1 + ? t('{{filters}} active filters', { filters: count }) + : t('{{filters}} active filter', { filters: count }), + + // Quick filter toolbar field + toolbarQuickFilterPlaceholder: t('Search…'), + + toolbarQuickFilterLabel: t('Search'), + toolbarQuickFilterDeleteIconLabel: t('Clear'), + + // Export selector toolbar button text + toolbarExport: t('Export'), + + toolbarExportLabel: t('Export'), + toolbarExportCSV: t('Download as CSV'), + toolbarExportPrint: t('Print'), + toolbarExportExcel: t('Download as Excel'), + + // Columns panel text + columnsPanelTextFieldLabel: t('Find column'), + + columnsPanelTextFieldPlaceholder: t('Column title'), + columnsPanelDragIconLabel: t('Reorder column'), + columnsPanelShowAllButton: t('Show all'), + columnsPanelHideAllButton: t('Hide all'), + + // Filter panel text + filterPanelAddFilter: t('Add filter'), + + filterPanelDeleteIconLabel: t('Delete'), + filterPanelLinkOperator: t('Logic operator'), + filterPanelOperators: t('Operator'), + filterPanelOperatorAnd: t('And'), + filterPanelOperatorOr: t('Or'), + filterPanelColumns: t('Columns'), + filterPanelInputLabel: t('Value'), + filterPanelInputPlaceholder: t('Filter value'), + + // Filter operators text + filterOperatorContains: t('contains'), + + filterOperatorEquals: t('equals'), + filterOperatorStartsWith: t('starts with'), + filterOperatorEndsWith: t('ends with'), + filterOperatorIs: t('is'), + filterOperatorNot: t('is not'), + filterOperatorAfter: t('is after'), + filterOperatorOnOrAfter: t('is on or after'), + filterOperatorBefore: t('is before'), + filterOperatorOnOrBefore: t('is on or before'), + filterOperatorIsEmpty: t('is empty'), + filterOperatorIsNotEmpty: t('is not empty'), + filterOperatorIsAnyOf: t('is any of'), + + // Filter values text + filterValueAny: t('any'), + + filterValueTrue: t('true'), + filterValueFalse: t('false'), + + // Column menu text + columnMenuLabel: t('Menu'), + + columnMenuShowColumns: t('Show columns'), + columnMenuFilter: t('Filter'), + columnMenuHideColumn: t('Hide'), + columnMenuUnsort: t('Unsort'), + columnMenuSortAsc: t('Sort by ASC'), + columnMenuSortDesc: t('Sort by DESC'), + + // Column header text + columnHeaderFiltersTooltipActive: (count) => + count !== 1 + ? t('{{filters}} active filters', { filters: count }) + : t('1 active filter'), + + columnHeaderFiltersLabel: t('Show filters'), + columnHeaderSortIconLabel: t('Sort'), + + // Rows selected footer text + footerRowSelected: (count) => + count !== 1 + ? t('{{rows}} rows selected', { + rows: count.toLocaleString(locale), + }) + : t('{{rows}} row selected', { + rows: count.toLocaleString(locale), + }), + + // Total row amount footer text + footerTotalRows: t('Total Rows:'), + + // Total visible row amount footer text + footerTotalVisibleRows: (visibleCount, totalCount) => + t('{{visible}} of {{total}}', { + visible: visibleCount.toLocaleString(locale), + total: totalCount.toLocaleString(locale), + }), + + // Checkbox selection text + checkboxSelectionHeaderName: t('Checkbox selection'), + + checkboxSelectionSelectAllRows: t('Select all rows'), + checkboxSelectionUnselectAllRows: t('Unselect all rows'), + checkboxSelectionSelectRow: t('Select row'), + checkboxSelectionUnselectRow: t('Unselect row'), + + // Boolean cell text + booleanCellTrueLabel: t('yes'), + + booleanCellFalseLabel: t('no'), + + // Actions cell more text + actionsCellMore: t('more'), + + // Column pinning text + pinToLeft: t('Pin to left'), + + pinToRight: t('Pin to right'), + unpin: t('Unpin'), + + // Tree Data + treeDataGroupingHeaderName: t('Group'), + + treeDataExpand: t('see children'), + treeDataCollapse: t('hide children'), + + // Grouping columns + groupingColumnHeaderName: t('Group'), + + groupColumn: (name) => t('Group by {{name}}', name), + unGroupColumn: (name) => t('Stop grouping by {{name}}', name), + + // Master/detail + detailPanelToggle: t('Detail panel toggle'), + + expandDetailPanel: t('Expand'), + collapseDetailPanel: t('Collapse'), + + // Used core components translation keys + MuiTablePagination: tablePaginationLocaleText, + + // Row reordering text + rowReorderingHeaderName: t('Row reordering'), + + // Aggregation + aggregationMenuItemHeader: t('Aggregation'), + + aggregationFunctionLabelSum: t('sum'), + aggregationFunctionLabelAvg: t('avg'), + aggregationFunctionLabelMin: t('min'), + aggregationFunctionLabelMax: t('max'), + aggregationFunctionLabelSize: t('size'), + }), + [t, locale], + ); +}; + +export const useTablePaginationLocaleText = + (): Partial => { + const { t } = useTranslation(); + + const localeText = useMemo( + (): Partial => ({ + getItemAriaLabel: (type) => { + switch (type) { + case 'first': + return t('first'); + case 'last': + return t('last'); + case 'next': + return t('next'); + case 'previous': + return t('previous'); + } + }, + labelRowsPerPage: t('Rows per page:'), + labelDisplayedRows: ({ from, to, count }) => + t('{{from}}-{{to}} of {{total}}', { from, to, total: count }), + }), + [t], + ); + + return localeText; + };