diff --git a/.github/workflows/i18n-unused-keys.yml b/.github/workflows/i18n-unused-keys.yml index 79f95d3b27f..2e66dfa9877 100644 --- a/.github/workflows/i18n-unused-keys.yml +++ b/.github/workflows/i18n-unused-keys.yml @@ -59,8 +59,8 @@ jobs: run: | PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") - # Format the unused keys list correctly, filtering out empty entries - FILTERED_KEYS=$(echo "$unused_keys" | jq -r '.[]' | grep -v '^\s*$' | sed 's/^/- `/;s/$/`/' ) + # Format the unused keys list as checkboxes for easy manual checking. + FILTERED_KEYS=$(echo "$unused_keys" | jq -r '.[]' | grep -v '^\s*$' | sed 's/^/- [ ] `/;s/$/`/' ) COMMENT_BODY=$(cat <; onClick: () => void; - infoTextCode: string; - actionTextCode: string; + infoTextCode: TranslationKeys; + actionTextCode: TranslationKeys; dataTestIdInitial: string; dataTestIdConfirm: string; - infoDescriptionCode?: string; - confirmActionTextCode?: string; + infoDescriptionCode?: TranslationKeys; + confirmActionTextCode?: TranslationKeys; }; export type TDialogProps = { diff --git a/client/src/components/Chat/Input/Files/Table/Columns.tsx b/client/src/components/Chat/Input/Files/Table/Columns.tsx index 3ca28bad8a2..8b8f52d8e73 100644 --- a/client/src/components/Chat/Input/Files/Table/Columns.tsx +++ b/client/src/components/Chat/Input/Files/Table/Columns.tsx @@ -1,4 +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'; @@ -7,10 +7,10 @@ import { Button, Checkbox, OpenAIMinimalIcon, AzureMinimalIcon } from '~/compone import ImagePreview from '~/components/Chat/Input/Files/ImagePreview'; import FilePreview from '~/components/Chat/Input/Files/FilePreview'; import { SortFilterHeader } from './SortFilterHeader'; -import { useLocalize, useMediaQuery } from '~/hooks'; +import { TranslationKeys, useLocalize, useMediaQuery } from '~/hooks'; import { formatDate, getFileType } from '~/utils'; -const contextMap = { +const contextMap: Record = { [FileContext.avatar]: 'com_ui_avatar', [FileContext.unknown]: 'com_ui_unknown', [FileContext.assistants]: 'com_ui_assistants', @@ -127,8 +127,8 @@ export const columns: ColumnDef[] = [ ), }} valueMap={{ - [FileSources.azure]: 'Azure', - [FileSources.openai]: 'OpenAI', + [FileSources.azure]: 'com_ui_azure', + [FileSources.openai]: 'com_ui_openai', [FileSources.local]: 'com_ui_host', }} /> @@ -182,7 +182,7 @@ export const columns: ColumnDef[] = [ const localize = useLocalize(); return (
- {localize(contextMap[context ?? FileContext.unknown] ?? 'com_ui_unknown')} + {localize(contextMap[context ?? FileContext.unknown])}
); }, @@ -212,4 +212,4 @@ export const columns: ColumnDef[] = [ return `${value}${suffix}`; }, }, -]; +]; \ No newline at end of file diff --git a/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx b/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx index 1b9a0cbe426..bb9247c15a0 100644 --- a/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx +++ b/client/src/components/Chat/Input/Files/Table/SortFilterHeader.tsx @@ -16,7 +16,7 @@ interface SortFilterHeaderProps extends React.HTMLAttributes; filters?: Record; - valueMap?: Record; + valueMap?: Record; } export function SortFilterHeader({ @@ -82,7 +82,7 @@ export function SortFilterHeader({ const translationKey = valueMap?.[value ?? '']; const filterValue = translationKey != null && translationKey.length - ? localize(translationKey as TranslationKeys) + ? localize(translationKey) : String(value); if (!filterValue) { return null; diff --git a/client/src/components/Chat/Input/Mention.tsx b/client/src/components/Chat/Input/Mention.tsx index c09c23b2bdd..de36cda09b7 100644 --- a/client/src/components/Chat/Input/Mention.tsx +++ b/client/src/components/Chat/Input/Mention.tsx @@ -6,7 +6,7 @@ import type { MentionOption, ConvoGenerator } from '~/common'; import useSelectMention from '~/hooks/Input/useSelectMention'; import { useAssistantsMapContext } from '~/Providers'; import useMentions from '~/hooks/Input/useMentions'; -import { useLocalize, useCombobox } from '~/hooks'; +import { useLocalize, useCombobox, TranslationKeys } from '~/hooks'; import { removeCharIfLast } from '~/utils'; import MentionItem from './MentionItem'; @@ -24,7 +24,7 @@ export default function Mention({ newConversation: ConvoGenerator; textAreaRef: React.MutableRefObject; commandChar?: string; - placeholder?: string; + placeholder?: TranslationKeys; includeAssistants?: boolean; }) { const localize = useLocalize(); @@ -162,7 +162,7 @@ export default function Mention({
void; - setActiveSetting: React.Dispatch>; + setting: ForkOptions; + onClick: (setting: ForkOptions) => void; + setActiveSetting: React.Dispatch>; sideOffset?: number; timeoutRef: React.MutableRefObject; hoverInfo?: React.ReactNode | string; @@ -31,11 +31,11 @@ interface PopoverButtonProps { hoverDescription?: React.ReactNode | string; } -const optionLabels = { +const optionLabels: Record = { [ForkOptions.DIRECT_PATH]: 'com_ui_fork_visible', [ForkOptions.INCLUDE_BRANCHES]: 'com_ui_fork_branches', [ForkOptions.TARGET_LEVEL]: 'com_ui_fork_all_target', - default: 'com_ui_fork_from_message', + [ForkOptions.DEFAULT]: 'com_ui_fork_from_message', }; const PopoverButton: React.FC = ({ @@ -65,10 +65,10 @@ const PopoverButton: React.FC = ({ clearTimeout(timeoutRef.current); } timeoutRef.current = setTimeout(() => { - setActiveSetting(optionLabels.default); + setActiveSetting(optionLabels[ForkOptions.DEFAULT]); }, 175); }} - className="mx-1 max-w-14 flex-1 rounded-lg border-2 bg-white text-gray-700 transition duration-300 ease-in-out hover:bg-gray-200 hover:text-gray-900 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-gray-100 " + className="mx-1 max-w-14 flex-1 rounded-lg border-2 bg-white text-gray-700 transition duration-300 ease-in-out hover:bg-gray-200 hover:text-gray-900 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-gray-100" type="button" > {children} @@ -77,18 +77,12 @@ const PopoverButton: React.FC = ({ (hoverTitle != null && hoverTitle !== '') || (hoverDescription != null && hoverDescription !== '')) && ( - +

- {hoverInfo != null && hoverInfo !== '' && hoverInfo} - {hoverTitle != null && hoverTitle !== '' && ( - {hoverTitle} - )} - {hoverDescription != null && hoverDescription !== '' && hoverDescription} + {hoverInfo && hoverInfo} + {hoverTitle && {hoverTitle}} + {hoverDescription && hoverDescription}

@@ -201,7 +195,7 @@ export default function Fork({ align="center" >
- {localize(activeSetting as TranslationKeys)} + {localize(activeSetting )} @@ -235,7 +229,7 @@ export default function Fork({ hoverTitle={ <> - {localize(optionLabels[ForkOptions.DIRECT_PATH] as TranslationKeys)} + {localize(optionLabels[ForkOptions.DIRECT_PATH])} } hoverDescription={localize('com_ui_fork_info_visible')} @@ -253,7 +247,7 @@ export default function Fork({ hoverTitle={ <> - {localize(optionLabels[ForkOptions.INCLUDE_BRANCHES] as TranslationKeys)} + {localize(optionLabels[ForkOptions.INCLUDE_BRANCHES])} } hoverDescription={localize('com_ui_fork_info_branches')} @@ -272,7 +266,7 @@ export default function Fork({ <> {`${localize( - optionLabels[ForkOptions.TARGET_LEVEL] as TranslationKeys, + optionLabels[ForkOptions.TARGET_LEVEL], )} (${localize('com_endpoint_default')})`} } diff --git a/client/src/components/Nav/Settings.tsx b/client/src/components/Nav/Settings.tsx index 7ad5fc18665..77123460ca1 100644 --- a/client/src/components/Nav/Settings.tsx +++ b/client/src/components/Nav/Settings.tsx @@ -1,4 +1,4 @@ -import { useState, useRef } from 'react'; +import React, { useState, useRef } from 'react'; import * as Tabs from '@radix-ui/react-tabs'; import { MessageSquare, Command } from 'lucide-react'; import { SettingsTabValues } from 'librechat-data-provider'; @@ -6,7 +6,7 @@ import type { TDialogProps } from '~/common'; import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react'; import { GearIcon, DataIcon, SpeechIcon, UserIcon, ExperimentIcon } from '~/components/svg'; import { General, Chat, Speech, Beta, Commands, Data, Account } from './SettingsTabs'; -import { useMediaQuery, useLocalize } from '~/hooks'; +import { useMediaQuery, useLocalize, TranslationKeys } from '~/hooks'; import { cn } from '~/utils'; export default function Settings({ open, onOpenChange }: TDialogProps) { @@ -47,6 +47,44 @@ export default function Settings({ open, onOpenChange }: TDialogProps) { } }; + const settingsTabs: { value: SettingsTabValues; icon: React.JSX.Element; label: TranslationKeys }[] = [ + { + value: SettingsTabValues.GENERAL, + icon: , + label: 'com_nav_setting_general', + }, + { + value: SettingsTabValues.CHAT, + icon: , + label: 'com_nav_setting_chat', + }, + { + value: SettingsTabValues.BETA, + icon: , + label: 'com_nav_setting_beta', + }, + { + value: SettingsTabValues.COMMANDS, + icon: , + label: 'com_nav_commands', + }, + { + value: SettingsTabValues.SPEECH, + icon: , + label: 'com_nav_setting_speech', + }, + { + value: SettingsTabValues.DATA, + icon: , + label: 'com_nav_setting_data', + }, + { + value: SettingsTabValues.ACCOUNT, + icon: , + label: 'com_nav_setting_account', + }, + ]; + const handleTabChange = (value: string) => { setActiveTab(value as SettingsTabValues); }; @@ -126,43 +164,7 @@ export default function Settings({ open, onOpenChange }: TDialogProps) { )} onKeyDown={handleKeyDown} > - {[ - { - value: SettingsTabValues.GENERAL, - icon: , - label: 'com_nav_setting_general', - }, - { - value: SettingsTabValues.CHAT, - icon: , - label: 'com_nav_setting_chat', - }, - { - value: SettingsTabValues.BETA, - icon: , - label: 'com_nav_setting_beta', - }, - { - value: SettingsTabValues.COMMANDS, - icon: , - label: 'com_nav_commands', - }, - { - value: SettingsTabValues.SPEECH, - icon: , - label: 'com_nav_setting_speech', - }, - { - value: SettingsTabValues.DATA, - icon: , - label: 'com_nav_setting_data', - }, - { - value: SettingsTabValues.ACCOUNT, - icon: , - label: 'com_nav_setting_account', - }, - ].map(({ value, icon, label }) => ( + {settingsTabs.map(({ value, icon, label }) => ( { const localize = useLocalize(); @@ -103,7 +104,7 @@ const renderDeleteButton = ( handleDeleteUser: () => void, isDeleting: boolean, isLocked: boolean, - localize: (key: string) => string, + localize: LocalizeFunction, ) => (
diff --git a/client/src/components/SidePanel/Builder/ActionsAuth.tsx b/client/src/components/SidePanel/Builder/ActionsAuth.tsx index c56a4891659..1d0c3eea1f6 100644 --- a/client/src/components/SidePanel/Builder/ActionsAuth.tsx +++ b/client/src/components/SidePanel/Builder/ActionsAuth.tsx @@ -34,7 +34,7 @@ export default function ActionsAuth({ disableOAuth }: { disableOAuth?: boolean }
- {localize(`com_ui_${type}` as TranslationKeys)} + {localize(getAuthLocalizationKey(type))}