diff --git a/client/src/components/Chat/Input/Files/Table/Columns.tsx b/client/src/components/Chat/Input/Files/Table/Columns.tsx index 09f02eaf49..5b53a06f46 100644 --- a/client/src/components/Chat/Input/Files/Table/Columns.tsx +++ b/client/src/components/Chat/Input/Files/Table/Columns.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/rules-of-hooks */ import { ArrowUpDown, Database } from 'lucide-react'; import { FileSources, FileContext } from 'librechat-data-provider'; import type { ColumnDef } from '@tanstack/react-table'; @@ -8,37 +9,43 @@ import { SortFilterHeader } from './SortFilterHeader'; import { OpenAIMinimalIcon } from '~/components/svg'; import { Button, Checkbox } from '~/components/ui'; import { formatDate, getFileType } from '~/utils'; +import useLocalize from '~/hooks/useLocalize'; const contextMap = { - [FileContext.avatar]: 'Avatar', - [FileContext.unknown]: 'Unknown', - [FileContext.assistants]: 'Assistants', - [FileContext.image_generation]: 'Image Gen', - [FileContext.assistants_output]: 'Assistant Output', - [FileContext.message_attachment]: 'Attachment', + [FileContext.avatar]: 'com_ui_avatar', + [FileContext.unknown]: 'com_ui_unknown', + [FileContext.assistants]: 'com_ui_assistants', + [FileContext.image_generation]: 'com_ui_image_gen', + [FileContext.assistants_output]: 'com_ui_assistants_output', + [FileContext.message_attachment]: 'com_ui_attachment', }; export const columns: ColumnDef[] = [ { id: 'select', - header: ({ table }) => ( - table.toggleAllPageRowsSelected(!!value)} - aria-label="Select all" - className="flex" - /> - ), - cell: ({ row }) => ( - row.toggleSelected(!!value)} - aria-label="Select row" - className="flex" - /> - ), + header: ({ table }) => { + return ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + className="flex" + /> + ); + }, + cell: ({ row }) => { + return ( + row.toggleSelected(!!value)} + aria-label="Select row" + className="flex" + /> + ); + }, enableSorting: false, enableHiding: false, }, @@ -48,13 +55,14 @@ export const columns: ColumnDef[] = [ }, accessorKey: 'filename', header: ({ column }) => { + const localize = useLocalize(); return ( ); @@ -85,13 +93,14 @@ export const columns: ColumnDef[] = [ { accessorKey: 'updatedAt', header: ({ column }) => { + const localize = useLocalize(); return ( ); @@ -101,10 +110,11 @@ export const columns: ColumnDef[] = [ { accessorKey: 'source', header: ({ column }) => { + const localize = useLocalize(); return ( value === FileSources.local || value === FileSources.openai, @@ -112,12 +122,13 @@ export const columns: ColumnDef[] = [ }} valueMap={{ [FileSources.openai]: 'OpenAI', - [FileSources.local]: 'Host', + [FileSources.local]: 'com_ui_host', }} /> ); }, cell: ({ row }) => { + const localize = useLocalize(); const { source } = row.original; if (source === FileSources.openai) { return ( @@ -130,7 +141,7 @@ export const columns: ColumnDef[] = [ return (
- {'Host'} + {localize('com_ui_host')}
); }, @@ -138,10 +149,11 @@ export const columns: ColumnDef[] = [ { accessorKey: 'context', header: ({ column }) => { + const localize = useLocalize(); return ( value === FileContext[value ?? ''], @@ -153,9 +165,10 @@ export const columns: ColumnDef[] = [ }, cell: ({ row }) => { const { context } = row.original; + const localize = useLocalize(); return (
- {contextMap[context ?? FileContext.unknown] ?? 'Unknown'} + {localize(contextMap[context ?? FileContext.unknown] ?? 'com_ui_unknown')}
); }, @@ -163,13 +176,14 @@ export const columns: ColumnDef[] = [ { accessorKey: 'bytes', header: ({ column }) => { + const localize = useLocalize(); return ( ); diff --git a/client/src/components/Chat/Input/Files/Table/DataTable.tsx b/client/src/components/Chat/Input/Files/Table/DataTable.tsx index 5fd01964c4..23e7b8ea70 100644 --- a/client/src/components/Chat/Input/Files/Table/DataTable.tsx +++ b/client/src/components/Chat/Input/Files/Table/DataTable.tsx @@ -14,6 +14,7 @@ import type { VisibilityState, ColumnFiltersState, } from '@tanstack/react-table'; +import { FileContext } from 'librechat-data-provider'; import type { AugmentedColumnDef } from '~/common'; import type { TFile } from 'librechat-data-provider'; import { @@ -32,15 +33,25 @@ import { } from '~/components/ui'; import { useDeleteFilesFromTable } from '~/hooks/Files'; import { NewTrashIcon, Spinner } from '~/components/svg'; +import useLocalize from '~/hooks/useLocalize'; interface DataTableProps { columns: ColumnDef[]; data: TData[]; } +const contextMap = { + [FileContext.filename]: 'com_ui_name', + [FileContext.updatedAt]: 'com_ui_date', + [FileContext.source]: 'com_ui_storage', + [FileContext.context]: 'com_ui_context', + [FileContext.bytes]: 'com_ui_size', +}; + type Style = { width?: number | string; maxWidth?: number | string; minWidth?: number | string }; export default function DataTable({ columns, data }: DataTableProps) { + const localize = useLocalize(); const [isDeleting, setIsDeleting] = React.useState(false); const [rowSelection, setRowSelection] = React.useState({}); const [sorting, setSorting] = React.useState([]); @@ -80,21 +91,21 @@ export default function DataTable({ columns, data }: DataTablePro deleteFiles({ files: filesToDelete as TFile[] }); setRowSelection({}); }} - className="gap-2" + className="ml-1 gap-2 dark:hover:bg-gray-750/25 sm:ml-0" disabled={!table.getFilteredSelectedRowModel().rows.length || isDeleting} > {isDeleting ? ( - + ) : ( - + )} - Delete + {localize('com_ui_delete')} table.getColumn('filename')?.setFilterValue(event.target.value)} - className="max-w-sm dark:border-gray-700" + className="max-w-sm dark:border-gray-500" /> @@ -103,7 +114,10 @@ export default function DataTable({ columns, data }: DataTablePro {/* Filter Menu */} - + {table .getAllColumns() .filter((column) => column.getCanHide()) @@ -115,7 +129,7 @@ export default function DataTable({ columns, data }: DataTablePro checked={column.getIsVisible()} onCheckedChange={(value) => column.toggleVisibility(!!value)} > - {column.id} + {localize(contextMap[column.id])} ); })} @@ -190,7 +204,7 @@ export default function DataTable({ columns, data }: DataTablePro ) : ( - No results. + {localize('com_files_no_results')} )} @@ -199,24 +213,29 @@ export default function DataTable({ columns, data }: DataTablePro
- {table.getFilteredSelectedRowModel().rows.length} of{' '} - {table.getFilteredRowModel().rows.length} file(s) selected. + {localize( + 'com_files_number_selected', + `${table.getFilteredSelectedRowModel().rows.length}`, + `${table.getFilteredRowModel().rows.length}`, + )}
diff --git a/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx b/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx index 2aecbc952d..58887f9c58 100644 --- a/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx +++ b/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx @@ -9,6 +9,7 @@ import { DropdownMenuTrigger, } from '~/components/ui/DropdownMenu'; import { Button } from '~/components/ui/Button'; +import useLocalize from '~/hooks/useLocalize'; import { cn } from '~/utils'; interface SortFilterHeaderProps extends React.HTMLAttributes { @@ -25,6 +26,7 @@ export function SortFilterHeader({ filters, valueMap, }: SortFilterHeaderProps) { + const localize = useLocalize(); if (!column.getCanSort()) { return
{title}
; } @@ -53,36 +55,46 @@ export function SortFilterHeader({ )} - + column.toggleSorting(false)} className="cursor-pointer dark:text-white dark:hover:bg-gray-800" > - Asc + {localize('com_ui_ascending')} column.toggleSorting(true)} className="cursor-pointer dark:text-white dark:hover:bg-gray-800" > - Desc + {localize('com_ui_descending')} - + {filters && Object.entries(filters).map(([key, values]) => - values.map((value: string | number) => ( - { - column.setFilterValue(value); - }} - > - - {valueMap?.[value] ?? value} - - )), + values.map((value: string | number) => { + const localizedValue = localize(valueMap?.[value] ?? ''); + const filterValue = localizedValue?.length ? localizedValue : valueMap?.[value]; + if (!filterValue) { + return null; + } + return ( + { + column.setFilterValue(value); + }} + > + + {filterValue} + + ); + }), )} {filters && ( ({ }} > - Show All + {localize('com_ui_show_all')} )} diff --git a/client/src/components/SidePanel/Files/PanelTable.tsx b/client/src/components/SidePanel/Files/PanelTable.tsx index 28db9c2812..c75bf0774b 100644 --- a/client/src/components/SidePanel/Files/PanelTable.tsx +++ b/client/src/components/SidePanel/Files/PanelTable.tsx @@ -74,7 +74,7 @@ export default function DataTable({ columns, data }: DataTablePro <>
table.getColumn('filename')?.setFilterValue(event.target.value)} className="max-w-xs dark:border-gray-700" @@ -126,7 +126,7 @@ export default function DataTable({ columns, data }: DataTablePro ) : ( - No results. + {localize('com_files_no_results')} )} @@ -150,7 +150,7 @@ export default function DataTable({ columns, data }: DataTablePro onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()} > - Previous + {localize('com_ui_prev')}
diff --git a/client/src/components/ui/Checkbox.tsx b/client/src/components/ui/Checkbox.tsx index ce6d411b22..5cde4cc195 100644 --- a/client/src/components/ui/Checkbox.tsx +++ b/client/src/components/ui/Checkbox.tsx @@ -10,7 +10,7 @@ const Checkbox = React.forwardRef<