diff --git a/src/components/Datatable/BatchModule/ElementCounter/ElementCounter.test.tsx b/src/components/Datatable/BatchModule/ElementCounter/ElementCounter.test.tsx index 3368217b3..cafab26c5 100644 --- a/src/components/Datatable/BatchModule/ElementCounter/ElementCounter.test.tsx +++ b/src/components/Datatable/BatchModule/ElementCounter/ElementCounter.test.tsx @@ -1,26 +1,44 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { act, screen } from '@testing-library/react'; import ElementCounter, { getCounterContent } from './ElementCounter'; import { setup } from '../../../../utils/tests/setup'; import { DatatableStore, datatableInitialState } from '../../Datatable.store'; +// Mock translation function for tests +const mockT = (key: string, options?: any) => { + // Remove the 'sscds|' prefix if present + const cleanKey = key.replace('sscds|', ''); + + const translations: Record = { + 'datatable.elementCounter.selectedOf': `${ + options?.selectedLength || '' + } of ${options?.totalLength || ''} selected`, + 'datatable.elementCounter.noData': 'No data', + 'datatable.selection.selectAll': 'Select All', + 'datatable.selection.selectNone': 'Select None', + }; + + return translations[cleanKey] || key; +}; + describe('getCounterContent', () => { it('should return No Data when "totalLength" is 0', () => { - setup(getCounterContent(0)); + setup(getCounterContent(0, mockT as any, 0)); expect(screen.getByTestId('counter-content')).toHaveTextContent('No data'); }); it('should return No Data when "totalLength" is 0 and "selectedLength" is greater than 0', () => { - setup(getCounterContent(0, 500)); + setup(getCounterContent(0, mockT as any, 500)); expect(screen.getByTestId('counter-content')).toHaveTextContent('No data'); }); it('should return correct count when "totalLength" is greater than 0', () => { - setup(getCounterContent(1000)); + setup(getCounterContent(1000, mockT as any, 0)); expect(screen.getByTestId('counter-content')).toHaveTextContent('1K'); }); it('should return correct count when "totalLength" and "selectedLength" are greater than 0', () => { - setup(getCounterContent(1000, 500)); + setup(getCounterContent(1000, mockT as any, 500)); expect(screen.getByTestId('counter-content')).toHaveTextContent( '500 of 1K selected', ); diff --git a/src/components/Datatable/BatchModule/ElementCounter/ElementCounter.tsx b/src/components/Datatable/BatchModule/ElementCounter/ElementCounter.tsx index de6a387d7..f902223a6 100644 --- a/src/components/Datatable/BatchModule/ElementCounter/ElementCounter.tsx +++ b/src/components/Datatable/BatchModule/ElementCounter/ElementCounter.tsx @@ -1,6 +1,7 @@ import { useEffect, useState } from 'react'; import { isPositive } from 'ramda-adjunct'; import styled from 'styled-components'; +import { TFunction } from 'i18next'; import { Text } from '../../../Text'; import { abbreviateNumber, getColor, getSpace } from '../../../../utils'; @@ -11,6 +12,7 @@ import { DatatableStore } from '../../Datatable.store'; import { ElementCounterProps } from './ElementCounter.types'; import { Inline } from '../../../layout'; import { SpaceSizes } from '../../../../theme'; +import { useSafeTranslation } from '../../../../hooks/useSafeTranslation'; const SelectionButton = styled.button` display: inline-flex; @@ -29,15 +31,20 @@ const SelectionButton = styled.button` } `; -export const getCounterContent = (totalLength: number, selectedLength = 0) => ( +export const getCounterContent = ( + totalLength: number, + t: TFunction<['sscds'], undefined>, + selectedLength = 0, +) => ( ); @@ -55,6 +62,7 @@ const ElementCounter = ({ hasSelection, hasOnlyPerPageSelection, }: ElementCounterProps) => { + const { t } = useSafeTranslation(); const { selectedIds, hasExclusiveSelection } = DatatableStore.useState( (s) => ({ selectedIds: s.selectedIds, @@ -74,7 +82,7 @@ const ElementCounter = ({ ? dataSize - localSelectedLength : localSelectedLength; - const content = getCounterContent(dataSize, computedSelectedLength); + const content = getCounterContent(dataSize, t, computedSelectedLength); const handleSelectAllClick = () => { setLocalSelectedLength(0); @@ -111,7 +119,7 @@ const ElementCounter = ({ {localSelectedLength > 0 && ( @@ -132,12 +140,12 @@ const ElementCounter = ({ actions={[ { name: 'select-all', - label: 'Select All', + label: t('sscds|datatable.selection.selectAll'), onClick: handleSelectAllClick, }, { name: 'select-none', - label: 'Select None', + label: t('sscds|datatable.selection.selectNone'), onClick: handleSelectNoneClick, }, ]} diff --git a/src/components/Datatable/Table/components/LoadingOverlay.tsx b/src/components/Datatable/Table/components/LoadingOverlay.tsx index ab50bbc6b..7de00a8ad 100644 --- a/src/components/Datatable/Table/components/LoadingOverlay.tsx +++ b/src/components/Datatable/Table/components/LoadingOverlay.tsx @@ -5,6 +5,7 @@ import { LoadingOverlayProps } from './LoadingOverlay.types'; import { Spinner } from '../../../Spinner'; import Button from '../../../ButtonV2/Button'; import { Inline, Padbox } from '../../../layout'; +import { useSafeTranslation } from '../../../../hooks/useSafeTranslation'; const overlayStyles = css` position: absolute; @@ -46,31 +47,34 @@ const LoadingBackground = styled.div` opacity: 0.75; `; -const LoadingOverlay = ({ isCancelable, onCancel }: LoadingOverlayProps) => ( - - - - - {isCancelable ? ( - - - Loading - - - ) : ( - - )} - - - -); +const LoadingOverlay = ({ isCancelable, onCancel }: LoadingOverlayProps) => { + const { t } = useSafeTranslation(); + return ( + + + + + {isCancelable ? ( + + + {t('sscds|loading')} + + + ) : ( + + )} + + + + ); +}; export default LoadingOverlay; diff --git a/src/components/Datatable/Table/components/NoMatchingData.tsx b/src/components/Datatable/Table/components/NoMatchingData.tsx index f183c95dd..9c084a637 100644 --- a/src/components/Datatable/Table/components/NoMatchingData.tsx +++ b/src/components/Datatable/Table/components/NoMatchingData.tsx @@ -4,6 +4,7 @@ import { pxToRem } from '../../../../utils'; import { H4 } from '../../../Heading'; import Paragraph from '../../../Paragraph/Paragraph'; import { TextSizes } from '../../../Text/Text.enums'; +import { useSafeTranslation } from '../../../../hooks/useSafeTranslation'; const ListItem = styled.li` margin-left: ${pxToRem(16)}; @@ -13,24 +14,24 @@ const ListItem = styled.li` } `; -const NoMatchingData = () => ( - <> -

- No items match your current filters -

- - You could try - - -
    - - using "OR" instead of "AND" to combine your - queries - - checking your queries for typos -
-
- -); +const NoMatchingData = () => { + const { t } = useSafeTranslation(); + return ( + <> +

+ {t('sscds|datatable.noMatchingData.title')} +

+ + {t('sscds|datatable.noMatchingData.description')} + + +
    + {t('sscds|datatable.noMatchingData.list.item1')} + {t('sscds|datatable.noMatchingData.list.item2')} +
+
+ + ); +}; export default NoMatchingData; diff --git a/src/components/_internal/BaseTable/Footer/GoToPage.tsx b/src/components/_internal/BaseTable/Footer/GoToPage.tsx index 5baa73fcc..ca0353f0b 100644 --- a/src/components/_internal/BaseTable/Footer/GoToPage.tsx +++ b/src/components/_internal/BaseTable/Footer/GoToPage.tsx @@ -7,6 +7,7 @@ import { Input } from '../../../forms'; import { GoToPageProps } from './GoToPage.types'; import { SpaceSizes } from '../../../../theme'; import { Text } from '../../../Text'; +import { useSafeTranslation } from '../../../../hooks/useSafeTranslation'; const SmallInput = styled(Input)` padding: ${pxToRem(8, 16)}; @@ -26,6 +27,7 @@ const SmallInput = styled(Input)` `; const GoToPage = ({ pageCount, onPageChange }: GoToPageProps) => { + const { t } = useSafeTranslation(); const inputRef = useRef(null); const handlePageChange = (e: KeyboardEvent) => { const { target, key } = e; @@ -48,7 +50,7 @@ const GoToPage = ({ pageCount, onPageChange }: GoToPageProps) => { return ( - Go to page: + {t('sscds|basetable.goToPage.label')} ( - <> - - -

Loading

-
- - This may take a few moments. - - -); +const LoadingNoData = () => { + const { t } = useSafeTranslation(); + return ( + <> + + +

{t('sscds|loading')}

+
+ + {t('sscds|basetable.loading.description')} + + + ); +}; export default LoadingNoData; diff --git a/src/components/_internal/BaseTable/components/NoData.tsx b/src/components/_internal/BaseTable/components/NoData.tsx index f2fd4738e..ccfa0e64f 100644 --- a/src/components/_internal/BaseTable/components/NoData.tsx +++ b/src/components/_internal/BaseTable/components/NoData.tsx @@ -1,14 +1,20 @@ +import { useSafeTranslation } from '../../../../hooks/useSafeTranslation'; import { H4 } from '../../../Heading'; import Paragraph from '../../../Paragraph/Paragraph'; import { TextSizes } from '../../../Text/Text.enums'; -const NoData = () => ( - <> -

No data available

- - There are no records in this database. - - -); +const NoData = () => { + const { t } = useSafeTranslation(); + return ( + <> +

+ {t('sscds|basetable.noData.title')} +

+ + {t('sscds|datatable.noRecords.title')} + + + ); +}; export default NoData; diff --git a/src/locales/cs-CZ.ts b/src/locales/cs-CZ.ts index 4b258b4bc..6054e055a 100644 --- a/src/locales/cs-CZ.ts +++ b/src/locales/cs-CZ.ts @@ -40,6 +40,19 @@ const locale = { 'datatable.selection.clearSelection': 'Zrušit výběr', 'datatable.selection.toggleAll': 'Přepnout výběr všech řádů', 'datatable.selection.toggleRow': 'Přepnout výběr řádku', + 'datatable.selection.selectAll': 'Vybrat vše', + 'datatable.selection.selectNone': 'Nevybrat', + 'datatable.elementCounter.selectedOf': + '{selectedLength} z {totalLength} vybráno', + 'datatable.elementCounter.noData': 'Žádná data', + 'datatable.noMatchingData.title': + 'Žádné položky neodpovídají vašim aktuálním filtrům', + 'datatable.noMatchingData.description': 'Můžete zkusit', + 'datatable.noMatchingData.list.item1': + 'použít "OR" místo "AND" pro kombinování vašich dotazů', + 'datatable.noMatchingData.list.item2': + 'zkontrolovat překlepy ve vašich dotazech', + 'datatable.noRecords.title': 'V této databázi nejsou žádné záznamy.', 'datatable.noData.title': 'Nenalezeny žádné výsledky', 'datatable.noData.list.description': 'Toto může nastat z důvodu, že:', 'datatable.noData.list.emptySet': 'datová sada je prázdná', @@ -84,5 +97,12 @@ const locale = { 'Přetahování bylo zrušeno. Sloupec {header} byl uvolněn.', 'datatable.settings.ordering.screenReader.notDroppableArea': 'Sloupec {activeHeader} již není nad oblastí, kam lze položku upustit.', + 'basetable.noData.title': 'Žádná data nejsou k dispozici', + 'basetable.noData.description': + 'Nejsou k dispozici žádné záznamy k zobrazení.', + 'basetable.loading.title': 'Načítám data', + 'basetable.loading.description': 'Může to chvíli trvat.', + 'basetable.goToPage.label': 'Jít na stránku:', + cancel: 'Zrušit', } as const; export default locale; diff --git a/src/locales/en-US.ts b/src/locales/en-US.ts index 56cc1f4e8..f06a3260f 100644 --- a/src/locales/en-US.ts +++ b/src/locales/en-US.ts @@ -41,6 +41,17 @@ const locale = { 'datatable.selection.toggleAll': 'Toggle select all', 'datatable.selection.toggleRow': 'Toggle select row', 'datatable.selection.selectAllCount': 'Select all {totalRowCount}', + 'datatable.selection.selectAll': 'Select All', + 'datatable.selection.selectNone': 'Select None', + 'datatable.elementCounter.selectedOf': + '{selectedLength} of {totalLength} selected', + 'datatable.elementCounter.noData': 'No data', + 'datatable.noMatchingData.title': 'No items match your current filters', + 'datatable.noMatchingData.description': 'You could try', + 'datatable.noMatchingData.list.item1': + 'using "OR" instead of "AND" to combine your queries', + 'datatable.noMatchingData.list.item2': 'checking your queries for typos', + 'datatable.noRecords.title': 'There are no records in this database.', 'datatable.noData.title': 'No results found', 'datatable.noData.list.description': 'This may happen because:', 'datatable.noData.list.emptySet': 'the data set is empty', @@ -85,5 +96,11 @@ const locale = { 'Dragging was cancelled. {header} column was dropped.', 'datatable.settings.ordering.screenReader.notDroppableArea': '{activeHeader} column is no longer over a droppable area.', + 'basetable.noData.title': 'No data available', + 'basetable.noData.description': 'There are no records to display.', + 'basetable.loading.title': 'Loading data', + 'basetable.loading.description': 'This may take a few moments.', + 'basetable.goToPage.label': 'Go to page:', + cancel: 'Cancel', } as const; export default locale; diff --git a/src/locales/es-ES.ts b/src/locales/es-ES.ts index 295f02b75..e51f3f8b7 100644 --- a/src/locales/es-ES.ts +++ b/src/locales/es-ES.ts @@ -41,6 +41,19 @@ const locale = { 'datatable.selection.clearSelection': 'Borrar selección', 'datatable.selection.toggleAll': 'Alternar selección de todas', 'datatable.selection.toggleRow': 'Alternar selección de la fila', + 'datatable.selection.selectAll': 'Seleccionar Todo', + 'datatable.selection.selectNone': 'Seleccionar Ninguno', + 'datatable.elementCounter.selectedOf': + '{selectedLength} de {totalLength} seleccionados', + 'datatable.elementCounter.noData': 'Sin datos', + 'datatable.noMatchingData.title': + 'Ningún elemento coincide con sus filtros actuales', + 'datatable.noMatchingData.description': 'Podría intentar', + 'datatable.noMatchingData.list.item1': + 'usar "OR" en lugar de "AND" para combinar sus consultas', + 'datatable.noMatchingData.list.item2': + 'revisar sus consultas en busca de errores tipográficos', + 'datatable.noRecords.title': 'No hay registros en esta base de datos.', 'datatable.noData.title': 'No se han encontrado resultados', 'datatable.noData.list.description': 'Esto puede ocurrir por:', 'datatable.noData.list.emptySet': 'el conjunto de datos está vacío', @@ -85,5 +98,11 @@ const locale = { 'Se canceló el arrastre. La columna {header} se soltó.', 'datatable.settings.ordering.screenReader.notDroppableArea': 'La columna {activeHeader} ya no está sobre un área donde se puede soltar.', + 'basetable.noData.title': 'No hay datos disponibles', + 'basetable.noData.description': 'No hay registros para mostrar.', + 'basetable.loading.title': 'Cargando datos', + 'basetable.loading.description': 'Esto puede tomar unos momentos.', + 'basetable.goToPage.label': 'Ir a la página:', + cancel: 'Cancelar', } as const; export default locale; diff --git a/src/locales/ja-JP.ts b/src/locales/ja-JP.ts index 790d9e479..53f6d68db 100644 --- a/src/locales/ja-JP.ts +++ b/src/locales/ja-JP.ts @@ -39,6 +39,18 @@ const locale = { 'datatable.selection.clearSelection': '選択をクリア', 'datatable.selection.toggleAll': '全選択/全解除', 'datatable.selection.toggleRow': '行の選択/解除', + 'datatable.selection.selectAll': 'すべて選択', + 'datatable.selection.selectNone': '選択解除', + 'datatable.elementCounter.selectedOf': + '{selectedLength} / {totalLength} 選択済み', + 'datatable.elementCounter.noData': 'データなし', + 'datatable.noMatchingData.title': + '現在のフィルターに一致するアイテムがありません', + 'datatable.noMatchingData.description': '以下の方法を試してみてください', + 'datatable.noMatchingData.list.item1': + 'クエリを組み合わせる際に"AND"の代わりに"OR"を使用する', + 'datatable.noMatchingData.list.item2': 'クエリのタイプミスを確認する', + 'datatable.noRecords.title': 'このデータベースにはレコードがありません。', 'datatable.noData.title': '結果が見つかりませんでした', 'datatable.noData.list.description': '以下の理由で発生することがあります:', 'datatable.noData.list.emptySet': 'データセットが空です', @@ -83,5 +95,11 @@ const locale = { 'ドラッグがキャンセルされました。{header} 列がドロップされました。', 'datatable.settings.ordering.screenReader.notDroppableArea': '{activeHeader} 列はもはやドロップ可能な領域にはありません。', + 'basetable.noData.title': 'データがありません', + 'basetable.noData.description': '表示するレコードがありません。', + 'basetable.loading.title': 'データを読み込み中', + 'basetable.loading.description': 'しばらくお待ちください。', + 'basetable.goToPage.label': 'ページに移動:', + cancel: 'キャンセル', } as const; export default locale; diff --git a/src/locales/pt-BR.ts b/src/locales/pt-BR.ts index 4a2bff587..680912105 100644 --- a/src/locales/pt-BR.ts +++ b/src/locales/pt-BR.ts @@ -41,6 +41,19 @@ const locale = { 'datatable.selection.clearSelection': 'Limpar seleção', 'datatable.selection.toggleAll': 'Alternar selecionar todos', 'datatable.selection.toggleRow': 'Alternar selecionar linha', + 'datatable.selection.selectAll': 'Selecionar Tudo', + 'datatable.selection.selectNone': 'Selecionar Nenhum', + 'datatable.elementCounter.selectedOf': + '{selectedLength} de {totalLength} selecionados', + 'datatable.elementCounter.noData': 'Sem dados', + 'datatable.noMatchingData.title': + 'Nenhum item corresponde aos seus filtros atuais', + 'datatable.noMatchingData.description': 'Você pode tentar', + 'datatable.noMatchingData.list.item1': + 'usar "OR" em vez de "AND" para combinar suas consultas', + 'datatable.noMatchingData.list.item2': + 'verificar se há erros de digitação em suas consultas', + 'datatable.noRecords.title': 'Não há registros neste banco de dados.', 'datatable.noData.title': 'Nenhum resultado encontrado', 'datatable.noData.list.description': 'Isso pode acontecer porque:', 'datatable.noData.list.emptySet': 'o conjunto de dados está vazio', @@ -85,5 +98,11 @@ const locale = { 'O arraste foi cancelado. A coluna {header} foi solta.', 'datatable.settings.ordering.screenReader.notDroppableArea': 'A coluna {activeHeader} não está mais em uma área onde pode ser solta.', + 'basetable.noData.title': 'Nenhum dado disponível', + 'basetable.noData.description': 'Não há registros para exibir.', + 'basetable.loading.title': 'Carregando dados', + 'basetable.loading.description': 'Isso pode levar alguns momentos.', + 'basetable.goToPage.label': 'Ir para a página:', + cancel: 'Cancelar', } as const; export default locale;