mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00
🔄 chore: Enforce 18next Language Keys (#5803)
* chore: enforcing language keys to adhere to the new standard. * chore: enforcing i18n forbids to write plain text in JSX markup * chore: enforcing i18n forbids to write plain text in JSX markup * fix: ci with checkbox for unused keys :) * refactor: removed all the unused `i18n` keys
This commit is contained in:
parent
2a506df443
commit
7f48030452
33 changed files with 200 additions and 219 deletions
6
.github/workflows/i18n-unused-keys.yml
vendored
6
.github/workflows/i18n-unused-keys.yml
vendored
|
@ -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 <<EOF
|
||||
### 🚨 Unused i18next Keys Detected
|
||||
|
@ -81,4 +81,4 @@ jobs:
|
|||
|
||||
- name: Fail workflow if unused keys found
|
||||
if: env.unused_keys != '[]'
|
||||
run: exit 1 # This makes the PR fail if unused keys exist
|
||||
run: exit 1
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -106,3 +106,4 @@ uploads/
|
|||
|
||||
# owner
|
||||
release/
|
||||
!/client/src/@types/i18next.d.ts
|
||||
|
|
9
client/src/@types/i18next.d.ts
vendored
Normal file
9
client/src/@types/i18next.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { defaultNS, resources } from '~/locales/i18n';
|
||||
|
||||
declare module 'i18next' {
|
||||
interface CustomTypeOptions {
|
||||
defaultNS: typeof defaultNS;
|
||||
resources: typeof resources.en;
|
||||
strictKeyChecks: true
|
||||
}
|
||||
}
|
|
@ -106,7 +106,7 @@ export type IconsRecord = {
|
|||
export type AgentIconMapProps = IconMapProps & { agentName?: string };
|
||||
|
||||
export type NavLink = {
|
||||
title: string;
|
||||
title: TranslationKeys;
|
||||
label?: string;
|
||||
icon: LucideIcon | React.FC;
|
||||
Component?: React.ComponentType;
|
||||
|
@ -370,12 +370,12 @@ export type TDangerButtonProps = {
|
|||
showText?: boolean;
|
||||
mutation?: UseMutationResult<unknown>;
|
||||
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 = {
|
||||
|
|
|
@ -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<any, TranslationKeys> = {
|
||||
[FileContext.avatar]: 'com_ui_avatar',
|
||||
[FileContext.unknown]: 'com_ui_unknown',
|
||||
[FileContext.assistants]: 'com_ui_assistants',
|
||||
|
@ -127,8 +127,8 @@ export const columns: ColumnDef<TFile>[] = [
|
|||
),
|
||||
}}
|
||||
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<TFile>[] = [
|
|||
const localize = useLocalize();
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{localize(contextMap[context ?? FileContext.unknown] ?? 'com_ui_unknown')}
|
||||
{localize(contextMap[context ?? FileContext.unknown])}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ interface SortFilterHeaderProps<TData, TValue> extends React.HTMLAttributes<HTML
|
|||
title: string;
|
||||
column: Column<TData, TValue>;
|
||||
filters?: Record<string, string[] | number[]>;
|
||||
valueMap?: Record<string, string>;
|
||||
valueMap?: Record<any, TranslationKeys>;
|
||||
}
|
||||
|
||||
export function SortFilterHeader<TData, TValue>({
|
||||
|
@ -82,7 +82,7 @@ export function SortFilterHeader<TData, TValue>({
|
|||
const translationKey = valueMap?.[value ?? ''];
|
||||
const filterValue =
|
||||
translationKey != null && translationKey.length
|
||||
? localize(translationKey as TranslationKeys)
|
||||
? localize(translationKey)
|
||||
: String(value);
|
||||
if (!filterValue) {
|
||||
return null;
|
||||
|
|
|
@ -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<HTMLTextAreaElement | null>;
|
||||
commandChar?: string;
|
||||
placeholder?: string;
|
||||
placeholder?: TranslationKeys;
|
||||
includeAssistants?: boolean;
|
||||
}) {
|
||||
const localize = useLocalize();
|
||||
|
@ -162,7 +162,7 @@ export default function Mention({
|
|||
<div className="popover border-token-border-light rounded-2xl border bg-white p-2 shadow-lg dark:bg-gray-700">
|
||||
<input
|
||||
// The user expects focus to transition to the input field when the popover is opened
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus
|
||||
|
||||
autoFocus
|
||||
ref={inputRef}
|
||||
placeholder={localize(placeholder)}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useRef } from 'react';
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { GitFork, InfoIcon } from 'lucide-react';
|
||||
import * as Popover from '@radix-ui/react-popover';
|
||||
|
@ -21,9 +21,9 @@ import store from '~/store';
|
|||
|
||||
interface PopoverButtonProps {
|
||||
children: React.ReactNode;
|
||||
setting: string;
|
||||
onClick: (setting: string) => void;
|
||||
setActiveSetting: React.Dispatch<React.SetStateAction<string>>;
|
||||
setting: ForkOptions;
|
||||
onClick: (setting: ForkOptions) => void;
|
||||
setActiveSetting: React.Dispatch<React.SetStateAction<TranslationKeys>>;
|
||||
sideOffset?: number;
|
||||
timeoutRef: React.MutableRefObject<NodeJS.Timeout | null>;
|
||||
hoverInfo?: React.ReactNode | string;
|
||||
|
@ -31,11 +31,11 @@ interface PopoverButtonProps {
|
|||
hoverDescription?: React.ReactNode | string;
|
||||
}
|
||||
|
||||
const optionLabels = {
|
||||
const optionLabels: Record<ForkOptions, TranslationKeys> = {
|
||||
[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<PopoverButtonProps> = ({
|
||||
|
@ -65,10 +65,10 @@ const PopoverButton: React.FC<PopoverButtonProps> = ({
|
|||
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<PopoverButtonProps> = ({
|
|||
(hoverTitle != null && hoverTitle !== '') ||
|
||||
(hoverDescription != null && hoverDescription !== '')) && (
|
||||
<HoverCardPortal>
|
||||
<HoverCardContent
|
||||
side="right"
|
||||
className="z-[999] w-80 dark:bg-gray-700"
|
||||
sideOffset={sideOffset}
|
||||
>
|
||||
<HoverCardContent side="right" className="z-[999] w-80 dark:bg-gray-700" sideOffset={sideOffset}>
|
||||
<div className="space-y-2">
|
||||
<p className="flex flex-col gap-2 text-sm text-gray-600 dark:text-gray-300">
|
||||
{hoverInfo != null && hoverInfo !== '' && hoverInfo}
|
||||
{hoverTitle != null && hoverTitle !== '' && (
|
||||
<span className="flex flex-wrap gap-1 font-bold">{hoverTitle}</span>
|
||||
)}
|
||||
{hoverDescription != null && hoverDescription !== '' && hoverDescription}
|
||||
{hoverInfo && hoverInfo}
|
||||
{hoverTitle && <span className="flex flex-wrap gap-1 font-bold">{hoverTitle}</span>}
|
||||
{hoverDescription && hoverDescription}
|
||||
</p>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
|
@ -201,7 +195,7 @@ export default function Fork({
|
|||
align="center"
|
||||
>
|
||||
<div className="flex h-6 w-full items-center justify-center text-sm dark:text-gray-200">
|
||||
{localize(activeSetting as TranslationKeys)}
|
||||
{localize(activeSetting )}
|
||||
<HoverCard openDelay={50}>
|
||||
<HoverCardTrigger asChild>
|
||||
<InfoIcon className="ml-auto flex h-4 w-4 gap-2 text-gray-500 dark:text-white/50" />
|
||||
|
@ -235,7 +229,7 @@ export default function Fork({
|
|||
hoverTitle={
|
||||
<>
|
||||
<GitCommit className="h-5 w-5 rotate-90" />
|
||||
{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={
|
||||
<>
|
||||
<GitBranchPlus className="h-4 w-4 rotate-180" />
|
||||
{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({
|
|||
<>
|
||||
<ListTree className="h-5 w-5" />
|
||||
{`${localize(
|
||||
optionLabels[ForkOptions.TARGET_LEVEL] as TranslationKeys,
|
||||
optionLabels[ForkOptions.TARGET_LEVEL],
|
||||
)} (${localize('com_endpoint_default')})`}
|
||||
</>
|
||||
}
|
||||
|
|
|
@ -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: <GearIcon />,
|
||||
label: 'com_nav_setting_general',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.CHAT,
|
||||
icon: <MessageSquare className="icon-sm" />,
|
||||
label: 'com_nav_setting_chat',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.BETA,
|
||||
icon: <ExperimentIcon />,
|
||||
label: 'com_nav_setting_beta',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.COMMANDS,
|
||||
icon: <Command className="icon-sm" />,
|
||||
label: 'com_nav_commands',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.SPEECH,
|
||||
icon: <SpeechIcon className="icon-sm" />,
|
||||
label: 'com_nav_setting_speech',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.DATA,
|
||||
icon: <DataIcon />,
|
||||
label: 'com_nav_setting_data',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.ACCOUNT,
|
||||
icon: <UserIcon />,
|
||||
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: <GearIcon />,
|
||||
label: 'com_nav_setting_general',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.CHAT,
|
||||
icon: <MessageSquare className="icon-sm" />,
|
||||
label: 'com_nav_setting_chat',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.BETA,
|
||||
icon: <ExperimentIcon />,
|
||||
label: 'com_nav_setting_beta',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.COMMANDS,
|
||||
icon: <Command className="icon-sm" />,
|
||||
label: 'com_nav_commands',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.SPEECH,
|
||||
icon: <SpeechIcon className="icon-sm" />,
|
||||
label: 'com_nav_setting_speech',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.DATA,
|
||||
icon: <DataIcon />,
|
||||
label: 'com_nav_setting_data',
|
||||
},
|
||||
{
|
||||
value: SettingsTabValues.ACCOUNT,
|
||||
icon: <UserIcon />,
|
||||
label: 'com_nav_setting_account',
|
||||
},
|
||||
].map(({ value, icon, label }) => (
|
||||
{settingsTabs.map(({ value, icon, label }) => (
|
||||
<Tabs.Trigger
|
||||
key={value}
|
||||
className={cn(
|
||||
|
|
|
@ -14,6 +14,7 @@ import { useDeleteUserMutation } from '~/data-provider';
|
|||
import { useAuthContext } from '~/hooks/AuthContext';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
import { LocalizeFunction } from '~/common';
|
||||
|
||||
const DeleteAccount = ({ disabled = false }: { title?: string; disabled?: boolean }) => {
|
||||
const localize = useLocalize();
|
||||
|
@ -103,7 +104,7 @@ const renderDeleteButton = (
|
|||
handleDeleteUser: () => void,
|
||||
isDeleting: boolean,
|
||||
isLocked: boolean,
|
||||
localize: (key: string) => string,
|
||||
localize: LocalizeFunction,
|
||||
) => (
|
||||
<button
|
||||
className={cn(
|
||||
|
|
|
@ -18,7 +18,6 @@ export default function PlusCommandSwitch() {
|
|||
id="plusCommand"
|
||||
checked={plusCommand}
|
||||
onCheckedChange={handleCheckedChange}
|
||||
f
|
||||
className="ml-4"
|
||||
data-testid="plusCommand"
|
||||
/>
|
||||
|
|
|
@ -18,7 +18,6 @@ export default function SlashCommandSwitch() {
|
|||
id="slashCommand"
|
||||
checked={slashCommand}
|
||||
onCheckedChange={handleCheckedChange}
|
||||
f
|
||||
data-testid="slashCommand"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -34,7 +34,7 @@ export default function ActionsAuth({ disableOAuth }: { disableOAuth?: boolean }
|
|||
</div>
|
||||
<div className="border-token-border-medium flex rounded-lg border text-sm hover:cursor-pointer">
|
||||
<div className="h-9 grow px-3 py-2">
|
||||
{localize(`com_ui_${type}` as TranslationKeys)}
|
||||
{localize(getAuthLocalizationKey(type))}
|
||||
</div>
|
||||
<div className="bg-token-border-medium w-px"></div>
|
||||
<button type="button" color="neutral" className="flex items-center gap-2 px-3">
|
||||
|
@ -269,6 +269,18 @@ const ApiKey = () => {
|
|||
);
|
||||
};
|
||||
|
||||
/** Returns the appropriate localization key for authentication type */
|
||||
function getAuthLocalizationKey(type: AuthTypeEnum): TranslationKeys {
|
||||
switch (type) {
|
||||
case AuthTypeEnum.ServiceHttp:
|
||||
return 'com_ui_api_key';
|
||||
case AuthTypeEnum.OAuth:
|
||||
return 'com_ui_oauth';
|
||||
default:
|
||||
return 'com_ui_none';
|
||||
}
|
||||
}
|
||||
|
||||
const OAuth = () => {
|
||||
const localize = useLocalize();
|
||||
const { register, watch, setValue } = useFormContext();
|
||||
|
|
|
@ -2,7 +2,7 @@ import { useMemo, useState } from 'react';
|
|||
import { OptionTypes } from 'librechat-data-provider';
|
||||
import type { DynamicSettingProps } from 'librechat-data-provider';
|
||||
import { Label, Checkbox, HoverCard, HoverCardTrigger } from '~/components/ui';
|
||||
import { useLocalize, useParameterEffects } from '~/hooks';
|
||||
import { TranslationKeys, useLocalize, useParameterEffects } from '~/hooks';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import OptionHover from './OptionHover';
|
||||
import { ESide } from '~/common';
|
||||
|
@ -66,7 +66,7 @@ function DynamicCheckbox({
|
|||
htmlFor={`${settingKey}-dynamic-checkbox`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label) ?? label : label || settingKey}{' '}
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}{' '}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}:{' '}
|
||||
|
@ -85,7 +85,7 @@ function DynamicCheckbox({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description) ?? description : description}
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { OptionTypes } from 'librechat-data-provider';
|
|||
import type { DynamicSettingProps } from 'librechat-data-provider';
|
||||
import { Label, HoverCard, HoverCardTrigger } from '~/components/ui';
|
||||
import ControlCombobox from '~/components/ui/ControlCombobox';
|
||||
import { useLocalize, useParameterEffects } from '~/hooks';
|
||||
import { TranslationKeys, useLocalize, useParameterEffects } from '~/hooks';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import OptionHover from './OptionHover';
|
||||
import { ESide } from '~/common';
|
||||
|
@ -93,7 +93,7 @@ function DynamicCombobox({
|
|||
htmlFor={`${settingKey}-dynamic-combobox`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label) ?? label : label || settingKey}
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}: {defaultValue})
|
||||
|
@ -105,10 +105,10 @@ function DynamicCombobox({
|
|||
<ControlCombobox
|
||||
displayValue={selectedValue}
|
||||
selectPlaceholder={
|
||||
selectPlaceholderCode === true ? localize(selectPlaceholder) : selectPlaceholder
|
||||
selectPlaceholderCode === true ? localize(selectPlaceholder as TranslationKeys) : selectPlaceholder
|
||||
}
|
||||
searchPlaceholder={
|
||||
searchPlaceholderCode === true ? localize(searchPlaceholder) : searchPlaceholder
|
||||
searchPlaceholderCode === true ? localize(searchPlaceholder as TranslationKeys) : searchPlaceholder
|
||||
}
|
||||
isCollapsed={isCollapsed}
|
||||
ariaLabel={settingKey}
|
||||
|
@ -120,7 +120,7 @@ function DynamicCombobox({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description) ?? description : description}
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { useMemo, useState } from 'react';
|
|||
import { OptionTypes } from 'librechat-data-provider';
|
||||
import type { DynamicSettingProps } from 'librechat-data-provider';
|
||||
import { Label, HoverCard, HoverCardTrigger, SelectDropDown } from '~/components/ui';
|
||||
import { useLocalize, useParameterEffects } from '~/hooks';
|
||||
import { TranslationKeys, useLocalize, useParameterEffects } from '~/hooks';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import OptionHover from './OptionHover';
|
||||
import { ESide } from '~/common';
|
||||
|
@ -78,7 +78,7 @@ function DynamicDropdown({
|
|||
htmlFor={`${settingKey}-dynamic-dropdown`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label) ?? label : label || settingKey}
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}: {defaultValue})
|
||||
|
@ -96,12 +96,12 @@ function DynamicDropdown({
|
|||
availableValues={options}
|
||||
containerClassName="w-full"
|
||||
id={`${settingKey}-dynamic-dropdown`}
|
||||
placeholder={placeholderCode ? localize(placeholder) ?? placeholder : placeholder}
|
||||
placeholder={placeholderCode ? localize(placeholder as TranslationKeys) ?? placeholder : placeholder}
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description) ?? description : description}
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { OptionTypes } from 'librechat-data-provider';
|
||||
import type { DynamicSettingProps } from 'librechat-data-provider';
|
||||
import { useLocalize, useDebouncedInput, useParameterEffects } from '~/hooks';
|
||||
import { useLocalize, useDebouncedInput, useParameterEffects, TranslationKeys } from '~/hooks';
|
||||
import { Label, Input, HoverCard, HoverCardTrigger } from '~/components/ui';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import OptionHover from './OptionHover';
|
||||
|
@ -73,7 +73,7 @@ function DynamicInput({
|
|||
htmlFor={`${settingKey}-dynamic-input`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label) || label : label || settingKey}{' '}
|
||||
{labelCode ? localize(label as TranslationKeys) || label : label || settingKey}{' '}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
(
|
||||
|
@ -90,7 +90,7 @@ function DynamicInput({
|
|||
disabled={readonly}
|
||||
value={inputValue ?? ''}
|
||||
onChange={handleInputChange}
|
||||
placeholder={placeholderCode ? localize(placeholder) || placeholder : placeholder}
|
||||
placeholder={placeholderCode ? localize(placeholder as TranslationKeys) || placeholder : placeholder}
|
||||
className={cn(
|
||||
'flex h-10 max-h-10 w-full resize-none border-none bg-surface-secondary px-3 py-2',
|
||||
)}
|
||||
|
@ -98,7 +98,7 @@ function DynamicInput({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description) || description : description}
|
||||
description={descriptionCode ? localize(description as TranslationKeys) || description : description}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { useMemo, useCallback } from 'react';
|
|||
import { OptionTypes } from 'librechat-data-provider';
|
||||
import type { DynamicSettingProps } from 'librechat-data-provider';
|
||||
import { Label, Slider, HoverCard, Input, InputNumber, HoverCardTrigger } from '~/components/ui';
|
||||
import { useLocalize, useDebouncedInput, useParameterEffects } from '~/hooks';
|
||||
import { useLocalize, useDebouncedInput, useParameterEffects, TranslationKeys } from '~/hooks';
|
||||
import { cn, defaultTextProps, optionText } from '~/utils';
|
||||
import { ESide, defaultDebouncedDelay } from '~/common';
|
||||
import { useChatContext } from '~/Providers';
|
||||
|
@ -117,7 +117,7 @@ function DynamicSlider({
|
|||
htmlFor={`${settingKey}-dynamic-setting`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label) ?? label : label || settingKey}{' '}
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}{' '}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}: {defaultValue})
|
||||
|
@ -176,7 +176,7 @@ function DynamicSlider({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description) ?? description : description}
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { useState, useMemo } from 'react';
|
|||
import { OptionTypes } from 'librechat-data-provider';
|
||||
import type { DynamicSettingProps } from 'librechat-data-provider';
|
||||
import { Label, Switch, HoverCard, HoverCardTrigger } from '~/components/ui';
|
||||
import { useLocalize, useParameterEffects } from '~/hooks';
|
||||
import { TranslationKeys, useLocalize, useParameterEffects } from '~/hooks';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import OptionHover from './OptionHover';
|
||||
import { ESide } from '~/common';
|
||||
|
@ -65,7 +65,7 @@ function DynamicSwitch({
|
|||
htmlFor={`${settingKey}-dynamic-switch`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label) ?? label : label || settingKey}{' '}
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}{' '}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}:{' '}
|
||||
|
@ -84,7 +84,7 @@ function DynamicSwitch({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description) ?? description : description}
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { OptionTypes } from 'librechat-data-provider';
|
||||
import type { DynamicSettingProps } from 'librechat-data-provider';
|
||||
import { Label, TextareaAutosize, HoverCard, HoverCardTrigger } from '~/components/ui';
|
||||
import { useLocalize, useDebouncedInput, useParameterEffects } from '~/hooks';
|
||||
import { useLocalize, useDebouncedInput, useParameterEffects, TranslationKeys } from '~/hooks';
|
||||
import { cn, defaultTextProps } from '~/utils';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import OptionHover from './OptionHover';
|
||||
|
@ -58,7 +58,7 @@ function DynamicTextarea({
|
|||
htmlFor={`${settingKey}-dynamic-textarea`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label) ?? label : label || settingKey}{' '}
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}{' '}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
(
|
||||
|
@ -75,7 +75,7 @@ function DynamicTextarea({
|
|||
disabled={readonly}
|
||||
value={inputValue ?? ''}
|
||||
onChange={setInputValue}
|
||||
placeholder={placeholderCode ? localize(placeholder) ?? placeholder : placeholder}
|
||||
placeholder={placeholderCode ? localize(placeholder as TranslationKeys) ?? placeholder : placeholder}
|
||||
className={cn(
|
||||
// TODO: configurable max height
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none rounded-lg bg-surface-secondary px-3 py-2 focus:outline-none',
|
||||
|
@ -84,7 +84,7 @@ function DynamicTextarea({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description) ?? description : description}
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { HoverCardPortal, HoverCardContent } from '~/components/ui';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { TranslationKeys, useLocalize } from '~/hooks';
|
||||
import { ESide } from '~/common';
|
||||
|
||||
type TOptionHoverProps = {
|
||||
|
@ -24,7 +24,7 @@ function OptionHover({
|
|||
if (disabled) {
|
||||
return null;
|
||||
}
|
||||
const text = langCode ? localize(description) : description;
|
||||
const text = langCode ? localize(description as TranslationKeys) : description;
|
||||
return (
|
||||
<HoverCardPortal>
|
||||
<HoverCardContent side={side} className={`z-[999] w-80 ${className}`} sideOffset={sideOffset}>
|
||||
|
|
|
@ -27,6 +27,7 @@ import {
|
|||
import { TrashIcon, Spinner } from '~/components/svg';
|
||||
import { useLocalize, useMediaQuery } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
import { LocalizeFunction } from '~/common';
|
||||
|
||||
type TableColumn<TData, TValue> = ColumnDef<TData, TValue> & {
|
||||
meta?: {
|
||||
|
@ -177,7 +178,7 @@ const DeleteButton = memo(
|
|||
isDeleting: boolean;
|
||||
disabled: boolean;
|
||||
isSmallScreen: boolean;
|
||||
localize: (key: string) => string;
|
||||
localize:LocalizeFunction;
|
||||
}) => {
|
||||
if (!onDelete) {
|
||||
return null;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useCallback, useRef, useEffect } from 'react';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { TranslationKeys, useLocalize } from '~/hooks';
|
||||
import { Minus, Plus } from 'lucide-react';
|
||||
|
||||
interface ModelParametersProps {
|
||||
|
@ -33,7 +33,7 @@ const ModelParameters: React.FC<ModelParametersProps> = ({
|
|||
const rangeRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const id = `model-parameter-${ariaLabel.toLowerCase().replace(/\s+/g, '-')}`;
|
||||
const displayLabel = label.startsWith('com_') ? localize(label) : label;
|
||||
const displayLabel = label.startsWith('com_') ? localize(label as TranslationKeys) : label;
|
||||
|
||||
const getDecimalPlaces = (num: number) => {
|
||||
const match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { MouseEvent, FocusEvent, KeyboardEvent } from 'react';
|
|||
import { useArchiveConversationMutation } from '~/data-provider';
|
||||
import { NotificationSeverity } from '~/common';
|
||||
import { useToastContext } from '~/Providers';
|
||||
import useLocalize from '../useLocalize';
|
||||
import useLocalize, { TranslationKeys } from '../useLocalize';
|
||||
import useNewConvo from '../useNewConvo';
|
||||
|
||||
export default function useArchiveHandler(
|
||||
|
@ -27,7 +27,7 @@ export default function useArchiveHandler(
|
|||
if (!convoId) {
|
||||
return;
|
||||
}
|
||||
const label = shouldArchive ? 'archive' : 'unarchive';
|
||||
const label: TranslationKeys = shouldArchive ? 'com_ui_archive_error' : 'com_ui_unarchive_error';
|
||||
archiveConvoMutation.mutate(
|
||||
{ conversationId: convoId, isArchived: shouldArchive },
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ export default function useArchiveHandler(
|
|||
},
|
||||
onError: () => {
|
||||
showToast({
|
||||
message: localize(`com_ui_${label}_error`),
|
||||
message: localize(label),
|
||||
severity: NotificationSeverity.ERROR,
|
||||
showIcon: true,
|
||||
});
|
||||
|
|
|
@ -69,6 +69,7 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
|
||||
const displayToast = useCallback(() => {
|
||||
if (errors.length > 1) {
|
||||
// TODO: this should not be a dynamic localize input!!
|
||||
const errorList = Array.from(new Set(errors))
|
||||
.map((e, i) => `${i > 0 ? '• ' : ''}${localize(e) || e}\n`)
|
||||
.join('');
|
||||
|
@ -78,6 +79,7 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
duration: 5000,
|
||||
});
|
||||
} else if (errors.length === 1) {
|
||||
// TODO: this should not be a dynamic localize input!!
|
||||
const message = localize(errors[0]) || errors[0];
|
||||
showToast({
|
||||
message,
|
||||
|
|
|
@ -36,6 +36,7 @@ describe('i18next translation tests', () => {
|
|||
|
||||
it('should return an empty string for an invalid key', () => {
|
||||
i18n.changeLanguage('en');
|
||||
// @ts-ignore
|
||||
expect(i18n.t('invalid-key')).toBe('');
|
||||
});
|
||||
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
"com_auth_email_verification_failed_token_missing": "Verification failed, token missing",
|
||||
"com_auth_email_verification_in_progress": "Verifying your email, please wait",
|
||||
"com_auth_email_verification_invalid": "Invalid email verification",
|
||||
"com_auth_email_verification_rate_limited": "Too many requests. Please try again later",
|
||||
"com_auth_email_verification_redirecting": "Redirecting in {{0}} seconds...",
|
||||
"com_auth_email_verification_resend_prompt": "Didn't receive the email?",
|
||||
"com_auth_email_verification_success": "Email verified successfully",
|
||||
|
@ -116,7 +115,6 @@
|
|||
"com_auth_registration_success_generic": "Please check your email to verify your email address.",
|
||||
"com_auth_registration_success_insecure": "Registration successful.",
|
||||
"com_auth_reset_password": "Reset your password",
|
||||
"com_auth_reset_password_email_sent": "If the user is registered, an email will be sent to the inbox.",
|
||||
"com_auth_reset_password_if_email_exists": "If an account with that email exists, an email with password reset instructions has been sent. Please make sure to check your spam folder.",
|
||||
"com_auth_reset_password_link_sent": "Email Sent",
|
||||
"com_auth_reset_password_success": "Password Reset Success",
|
||||
|
@ -128,7 +126,6 @@
|
|||
"com_auth_username": "Username (optional)",
|
||||
"com_auth_username_max_length": "Username must be less than 20 characters",
|
||||
"com_auth_username_min_length": "Username must be at least 2 characters",
|
||||
"com_auth_username_required": "Username is required",
|
||||
"com_auth_welcome_back": "Welcome back",
|
||||
"com_click_to_download": "(click here to download)",
|
||||
"com_download_expired": "(download expired)",
|
||||
|
@ -138,7 +135,6 @@
|
|||
"com_endpoint_agent_model": "Agent Model (Recommended: GPT-3.5)",
|
||||
"com_endpoint_agent_placeholder": "Please select an Agent",
|
||||
"com_endpoint_ai": "AI",
|
||||
"com_endpoint_anthropic_custom_name_placeholder": "Set a custom name for Anthropic",
|
||||
"com_endpoint_anthropic_maxoutputtokens": "Maximum number of tokens that can be generated in the response. Specify a lower value for shorter responses and a higher value for longer responses. Note: models may stop before reaching this maximum.",
|
||||
"com_endpoint_anthropic_prompt_cache": "Prompt caching allows reusing large context or instructions across API calls, reducing costs and latency",
|
||||
"com_endpoint_anthropic_temp": "Ranges from 0 to 1. Use temp closer to 0 for analytical / multiple choice, and closer to 1 for creative and generative tasks. We recommend altering this or Top P but not both.",
|
||||
|
@ -147,11 +143,6 @@
|
|||
"com_endpoint_assistant": "Assistant",
|
||||
"com_endpoint_assistant_model": "Assistant Model",
|
||||
"com_endpoint_assistant_placeholder": "Please select an Assistant from the right-hand Side Panel",
|
||||
"com_endpoint_bing_context_placeholder": "Bing can use up to 7k tokens for 'context', which it can reference for the conversation. The specific limit is not known but may run into errors exceeding 7k tokens",
|
||||
"com_endpoint_bing_enable_sydney": "Enable Sydney",
|
||||
"com_endpoint_bing_jailbreak": "Jailbreak",
|
||||
"com_endpoint_bing_system_message_placeholder": "WARNING: Misuse of this feature can get you BANNED from using Bing! Click on 'System Message' for full instructions and the default message if omitted, which is the 'Sydney' preset that is considered safe.",
|
||||
"com_endpoint_bing_to_enable_sydney": "To enable Sydney",
|
||||
"com_endpoint_completion": "Completion",
|
||||
"com_endpoint_completion_model": "Completion Model (Recommended: GPT-4)",
|
||||
"com_endpoint_config_click_here": "Click Here",
|
||||
|
@ -161,16 +152,8 @@
|
|||
"com_endpoint_config_google_gemini_api": "(Gemini API)",
|
||||
"com_endpoint_config_google_service_key": "Google Service Account Key",
|
||||
"com_endpoint_config_key": "Set API Key",
|
||||
"com_endpoint_config_key_chatgpt": "To get your Access token For ChatGPT 'Free Version', login to",
|
||||
"com_endpoint_config_key_chatgpt_copy_token": "Copy access token.",
|
||||
"com_endpoint_config_key_chatgpt_then_visit": "then visit",
|
||||
"com_endpoint_config_key_edge_full_key_string": "to provide the full cookie strings.",
|
||||
"com_endpoint_config_key_edge_instructions": "instructions",
|
||||
"com_endpoint_config_key_encryption": "Your key will be encrypted and deleted at",
|
||||
"com_endpoint_config_key_expiry": "the expiry time",
|
||||
"com_endpoint_config_key_for": "Set API Key for",
|
||||
"com_endpoint_config_key_get_edge_key": "To get your Access token for Bing, login to",
|
||||
"com_endpoint_config_key_get_edge_key_dev_tool": "Use dev tools or an extension while logged into the site to copy the content of the _U cookie. If this fails, follow these",
|
||||
"com_endpoint_config_key_google_need_to": "You need to",
|
||||
"com_endpoint_config_key_google_service_account": "Create a Service Account",
|
||||
"com_endpoint_config_key_google_vertex_ai": "Enable Vertex AI",
|
||||
|
@ -180,7 +163,6 @@
|
|||
"com_endpoint_config_key_import_json_key_invalid": "Invalid Service Account JSON Key, Did you import the correct file?",
|
||||
"com_endpoint_config_key_import_json_key_success": "Successfully Imported Service Account JSON Key",
|
||||
"com_endpoint_config_key_name": "Key",
|
||||
"com_endpoint_config_key_name_placeholder": "Set API key first",
|
||||
"com_endpoint_config_key_never_expires": "Your key will never expire",
|
||||
"com_endpoint_config_placeholder": "Set your Key in the Header menu to chat.",
|
||||
"com_endpoint_config_value": "Enter value for",
|
||||
|
@ -190,12 +172,8 @@
|
|||
"com_endpoint_custom_name": "Custom Name",
|
||||
"com_endpoint_default": "default",
|
||||
"com_endpoint_default_blank": "default: blank",
|
||||
"com_endpoint_default_creative": "default: creative",
|
||||
"com_endpoint_default_empty": "default: empty",
|
||||
"com_endpoint_default_false": "default: false",
|
||||
"com_endpoint_default_with_num": "default: {{0}}",
|
||||
"com_endpoint_disabled_with_tools": "disabled with tools",
|
||||
"com_endpoint_disabled_with_tools_placeholder": "Disabled with Tools Selected",
|
||||
"com_endpoint_examples": " Presets",
|
||||
"com_endpoint_export": "Export",
|
||||
"com_endpoint_export_share": "Export/Share",
|
||||
|
@ -206,7 +184,6 @@
|
|||
"com_endpoint_google_temp": "Higher values = more random, while lower values = more focused and deterministic. We recommend altering this or Top P but not both.",
|
||||
"com_endpoint_google_topk": "Top-k changes how the model selects tokens for output. A top-k of 1 means the selected token is the most probable among all tokens in the model's vocabulary (also called greedy decoding), while a top-k of 3 means that the next token is selected from among the 3 most probable tokens (using temperature).",
|
||||
"com_endpoint_google_topp": "Top-p changes how the model selects tokens for output. Tokens are selected from most K (see topK parameter) probable to least until the sum of their probabilities equals the top-p value.",
|
||||
"com_endpoint_hide": "Hide",
|
||||
"com_endpoint_import": "Import",
|
||||
"com_endpoint_instructions_assistants": "Override Instructions",
|
||||
"com_endpoint_instructions_assistants_placeholder": "Overrides the instructions of the assistant. This is useful for modifying the behavior on a per-run basis.",
|
||||
|
@ -215,10 +192,7 @@
|
|||
"com_endpoint_message_new": "Message {{0}}",
|
||||
"com_endpoint_message_not_appendable": "Edit your message or Regenerate.",
|
||||
"com_endpoint_my_preset": "My Preset",
|
||||
"com_endpoint_new_topic": "New Topic",
|
||||
"com_endpoint_no_presets": "No presets yet, use the settings button to create one",
|
||||
"com_endpoint_not_available": "No endpoint available",
|
||||
"com_endpoint_not_implemented": "Not implemented",
|
||||
"com_endpoint_open_menu": "Open Menu",
|
||||
"com_endpoint_openai_custom_name_placeholder": "Set a custom name for the AI",
|
||||
"com_endpoint_openai_detail": "The resolution for Vision requests. \"Low\" is cheaper and faster, \"High\" is more detailed and expensive, and \"Auto\" will automatically choose between the two based on the image resolution.",
|
||||
|
@ -236,13 +210,11 @@
|
|||
"com_endpoint_output": "Output",
|
||||
"com_endpoint_plug_image_detail": "Image Detail",
|
||||
"com_endpoint_plug_resend_files": "Resend Files",
|
||||
"com_endpoint_plug_resend_images": "Resend Images",
|
||||
"com_endpoint_plug_set_custom_instructions_for_gpt_placeholder": "Set custom instructions to include in System Message. Default: none",
|
||||
"com_endpoint_plug_skip_completion": "Skip Completion",
|
||||
"com_endpoint_plug_use_functions": "Use Functions",
|
||||
"com_endpoint_presence_penalty": "Presence Penalty",
|
||||
"com_endpoint_preset": "preset",
|
||||
"com_endpoint_preset_clear_all_confirm": "Are you sure you want to delete all of your presets?",
|
||||
"com_endpoint_preset_default": "is now the default preset.",
|
||||
"com_endpoint_preset_default_item": "Default:",
|
||||
"com_endpoint_preset_default_none": "No default preset active.",
|
||||
|
@ -252,6 +224,7 @@
|
|||
"com_endpoint_preset_import": "Preset Imported!",
|
||||
"com_endpoint_preset_import_error": "There was an error importing your preset. Please try again.",
|
||||
"com_endpoint_preset_name": "Preset Name",
|
||||
"com_endpoint_preset_custom_name_placeholder": "something needs to go here. was empty",
|
||||
"com_endpoint_preset_save_error": "There was an error saving your preset. Please try again.",
|
||||
"com_endpoint_preset_selected": "Preset Active!",
|
||||
"com_endpoint_preset_selected_title": "Active!",
|
||||
|
@ -265,22 +238,15 @@
|
|||
"com_endpoint_prompt_prefix_placeholder": "Set custom instructions or context. Ignored if empty.",
|
||||
"com_endpoint_reasoning_effort": "Reasoning Effort",
|
||||
"com_endpoint_save_as_preset": "Save As Preset",
|
||||
"com_endpoint_save_convo_as_preset": "Save Conversation as Preset",
|
||||
"com_endpoint_search": "Search endpoint by name",
|
||||
"com_endpoint_set_custom_name": "Set a custom name, in case you can find this preset",
|
||||
"com_endpoint_show": "Show",
|
||||
"com_endpoint_show_what_settings": "Show {{0}} Settings",
|
||||
"com_endpoint_skip_hover": "Enable skipping the completion step, which reviews the final answer and generated steps",
|
||||
"com_endpoint_stop": "Stop Sequences",
|
||||
"com_endpoint_stop_placeholder": "Separate values by pressing `Enter`",
|
||||
"com_endpoint_system_message": "System Message",
|
||||
"com_endpoint_temperature": "Temperature",
|
||||
"com_endpoint_token_count": "Token count",
|
||||
"com_endpoint_tone_style": "Tone Style",
|
||||
"com_endpoint_top_k": "Top K",
|
||||
"com_endpoint_top_p": "Top P",
|
||||
"com_endpoint_use_active_assistant": "Use Active Assistant",
|
||||
"com_endpoint_view_options": "View Options",
|
||||
"com_error_expired_user_key": "Provided key for {{0}} expired at {{1}}. Please provide a new key and try again.",
|
||||
"com_error_files_dupe": "Duplicate file detected.",
|
||||
"com_error_files_empty": "Empty files are not allowed.",
|
||||
|
@ -290,12 +256,9 @@
|
|||
"com_error_files_upload_canceled": "The file upload request was canceled. Note: the file upload may still be processing and will need to be manually deleted.",
|
||||
"com_error_files_validation": "An error occurred while validating the file.",
|
||||
"com_error_input_length": "The latest message token count is too long, exceeding the token limit ({{0}} respectively). Please shorten your message, adjust the max context size from the conversation parameters, or fork the conversation to continue.",
|
||||
"com_error_invalid_action_error": "Request denied: The specified action domain is not allowed.",
|
||||
"com_error_invalid_request_error": "The AI service rejected the request due to an error. This could be caused by an invalid API key or an improperly formatted request.",
|
||||
"com_error_invalid_user_key": "Invalid key provided. Please provide a valid key and try again.",
|
||||
"com_error_moderation": "It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We're unable to proceed with this specific topic. If you have any other questions or topics you'd like to explore, please edit your message, or create a new conversation.",
|
||||
"com_error_no_base_url": "No base URL found. Please provide one and try again.",
|
||||
"com_error_no_system_messages": "The selected AI service or model does not support system messages. Try using prompts instead of custom instructions.",
|
||||
"com_error_no_user_key": "No key found. Please provide a key and try again.",
|
||||
"com_files_filter": "Filter files...",
|
||||
"com_files_no_results": "No results.",
|
||||
|
@ -304,8 +267,6 @@
|
|||
"com_hide_examples": "Hide Examples",
|
||||
"com_nav_account_settings": "Account Settings",
|
||||
"com_nav_always_make_prod": "Always make new versions production",
|
||||
"com_nav_archive_all": "Archive all",
|
||||
"com_nav_archive_all_chats": "Archive all chats",
|
||||
"com_nav_archive_created_at": "Date Archived",
|
||||
"com_nav_archive_name": "Name",
|
||||
"com_nav_archived_chats": "Archived chats",
|
||||
|
@ -333,10 +294,7 @@
|
|||
"com_nav_clear_conversation": "Clear conversations",
|
||||
"com_nav_clear_conversation_confirm_message": "Are you sure you want to clear all conversations? This is irreversible.",
|
||||
"com_nav_close_sidebar": "Close sidebar",
|
||||
"com_nav_command_settings": "Command Settings",
|
||||
"com_nav_command_settings_description": "Customize which commands are available in the chat",
|
||||
"com_nav_commands": "Commands",
|
||||
"com_nav_commands_tab": "Command Settings",
|
||||
"com_nav_confirm_clear": "Confirm Clear",
|
||||
"com_nav_conversation_mode": "Conversation Mode",
|
||||
"com_nav_convo_menu_options": "Conversation Menu Options",
|
||||
|
@ -344,7 +302,6 @@
|
|||
"com_nav_delete_account": "Delete account",
|
||||
"com_nav_delete_account_button": "Permanently delete my account",
|
||||
"com_nav_delete_account_confirm": "Delete account - are you sure?",
|
||||
"com_nav_delete_account_confirm_placeholder": "To proceed, type \"DELETE\" in the input field below",
|
||||
"com_nav_delete_account_email_placeholder": "Please enter your account email",
|
||||
"com_nav_delete_cache_storage": "Delete TTS cache storage",
|
||||
"com_nav_delete_data_info": "All your data will be deleted.",
|
||||
|
@ -376,13 +333,11 @@
|
|||
"com_nav_info_code_artifacts": "Enables the display of experimental code artifacts next to the chat",
|
||||
"com_nav_info_code_artifacts_agent": "Enables the use of code artifacts for this agent. By default, additional instructions specific to the use of artifacts are added, unless \"Custom Prompt Mode\" is enabled.",
|
||||
"com_nav_info_custom_prompt_mode": "When enabled, the default artifacts system prompt will not be included. All artifact-generating instructions must be provided manually in this mode.",
|
||||
"com_nav_info_delete_cache_storage": "This action will delete all cached TTS (Text-to-Speech) audio files stored on your device. Cached audio files are used to speed up playback of previously generated TTS audio, but they can consume storage space on your device.",
|
||||
"com_nav_info_enter_to_send": "When enabled, pressing `ENTER` will send your message. When disabled, pressing Enter will add a new line, and you'll need to press `CTRL + ENTER` / `⌘ + ENTER` to send your message.",
|
||||
"com_nav_info_fork_change_default": "`Visible messages only` includes just the direct path to the selected message. `Include related branches` adds branches along the path. `Include all to/from here` includes all connected messages and branches.",
|
||||
"com_nav_info_fork_split_target_setting": "When enabled, forking will commence from the target message to the latest message in the conversation, according to the behavior selected.",
|
||||
"com_nav_info_include_shadcnui": "When enabled, instructions for using shadcn/ui components will be included. shadcn/ui is a collection of re-usable components built using Radix UI and Tailwind CSS. Note: these are lengthy instructions, you should only enable if informing the LLM of the correct imports and components is important to you. For more information about these components, visit: https://ui.shadcn.com/",
|
||||
"com_nav_info_latex_parsing": "When enabled, LaTeX code in messages will be rendered as mathematical equations. Disabling this may improve performance if you don't need LaTeX rendering.",
|
||||
"com_nav_info_revoke": "This action will revoke and remove all the API keys that you have provided. You will need to re-enter these credentials to continue using those endpoints.",
|
||||
"com_nav_info_save_draft": "When enabled, the text and attachments you enter in the chat form will be automatically saved locally as drafts. These drafts will be available even if you reload the page or switch to a different conversation. Drafts are stored locally on your device and are deleted once the message is sent.",
|
||||
"com_nav_info_show_thinking": "When enabled, the chat will display the thinking dropdowns open by default, allowing you to view the AI's reasoning in real-time. When disabled, the thinking dropdowns will remain closed by default for a cleaner and more streamlined interface",
|
||||
"com_nav_info_user_name_display": "When enabled, the username of the sender will be shown above each message you send. When disabled, you will only see \"You\" above your messages.",
|
||||
|
@ -412,7 +367,6 @@
|
|||
"com_nav_log_out": "Log out",
|
||||
"com_nav_long_audio_warning": "Longer texts will take longer to process.",
|
||||
"com_nav_maximize_chat_space": "Maximize chat space",
|
||||
"com_nav_media_source_init_error": "Unable to prepare audio player. Please check your browser settings.",
|
||||
"com_nav_modular_chat": "Enable switching Endpoints mid-conversation",
|
||||
"com_nav_my_files": "My Files",
|
||||
"com_nav_no_search_results": "No search results found",
|
||||
|
@ -439,16 +393,12 @@
|
|||
"com_nav_setting_speech": "Speech",
|
||||
"com_nav_settings": "Settings",
|
||||
"com_nav_shared_links": "Shared links",
|
||||
"com_nav_shared_links_date_shared": "Date shared",
|
||||
"com_nav_shared_links_empty": "You have no shared links.",
|
||||
"com_nav_shared_links_manage": "Manage",
|
||||
"com_nav_shared_links_name": "Name",
|
||||
"com_nav_show_code": "Always show code when using code interpreter",
|
||||
"com_nav_show_thinking": "Open Thinking Dropdowns by Default",
|
||||
"com_nav_slash_command": "/-Command",
|
||||
"com_nav_slash_command_description": "Toggle command \"/\" for selecting a prompt via keyboard",
|
||||
"com_nav_source_buffer_error": "Error setting up audio playback. Please refresh the page.",
|
||||
"com_nav_source_chat": "View source chat",
|
||||
"com_nav_speech_cancel_error": "Unable to stop audio playback. You may need to refresh the page.",
|
||||
"com_nav_speech_to_text": "Speech to Text",
|
||||
"com_nav_stop_generating": "Stop generating",
|
||||
|
@ -493,7 +443,6 @@
|
|||
"com_ui_admin_settings": "Admin Settings",
|
||||
"com_ui_advanced": "Advanced",
|
||||
"com_ui_agent": "Agent",
|
||||
"com_ui_agent_already_shared_to_all": "This agent is already shared to all users",
|
||||
"com_ui_agent_delete_error": "There was an error deleting the agent",
|
||||
"com_ui_agent_deleted": "Successfully deleted agent",
|
||||
"com_ui_agent_duplicate_error": "There was an error duplicating the agent",
|
||||
|
@ -554,13 +503,10 @@
|
|||
"com_ui_bookmarks_update_error": "There was an error updating the bookmark",
|
||||
"com_ui_bookmarks_update_success": "Bookmark updated successfully",
|
||||
"com_ui_bulk_delete_error": "Failed to delete shared links",
|
||||
"com_ui_bulk_delete_partial_error": "Failed to delete {{0}} shared links",
|
||||
"com_ui_callback_url": "Callback URL",
|
||||
"com_ui_cancel": "Cancel",
|
||||
"com_ui_categories": "Categories",
|
||||
"com_ui_chat": "Chat",
|
||||
"com_ui_chat_history": "Chat History",
|
||||
"com_ui_chats": "chats",
|
||||
"com_ui_clear": "Clear",
|
||||
"com_ui_clear_all": "Clear all",
|
||||
"com_ui_client_id": "Client ID",
|
||||
|
@ -574,7 +520,6 @@
|
|||
"com_ui_confirm_action": "Confirm Action",
|
||||
"com_ui_confirm_admin_use_change": "Changing this setting will block access for admins, including yourself. Are you sure you want to proceed?",
|
||||
"com_ui_confirm_change": "Confirm Change",
|
||||
"com_ui_connect": "Connect",
|
||||
"com_ui_context": "Context",
|
||||
"com_ui_continue": "Continue",
|
||||
"com_ui_controls": "Controls",
|
||||
|
@ -629,11 +574,9 @@
|
|||
"com_ui_download_artifact": "Download Artifact",
|
||||
"com_ui_download_error": "Error downloading file. The file may have been deleted.",
|
||||
"com_ui_drag_drop": "something needs to go here. was empty",
|
||||
"com_ui_drag_drop_file": "Drag and drop a file here",
|
||||
"com_ui_dropdown_variables": "Dropdown variables:",
|
||||
"com_ui_dropdown_variables_info": "Create custom dropdown menus for your prompts: `{{variable_name:option1|option2|option3}}`",
|
||||
"com_ui_duplicate": "Duplicate",
|
||||
"com_ui_duplicate_agent_confirm": "Are you sure you want to duplicate this agent?",
|
||||
"com_ui_duplication_error": "There was an error duplicating the conversation",
|
||||
"com_ui_duplication_processing": "Duplicating conversation...",
|
||||
"com_ui_duplication_success": "Successfully duplicated conversation",
|
||||
|
@ -645,17 +588,14 @@
|
|||
"com_ui_enter_api_key": "Enter API Key",
|
||||
"com_ui_enter_openapi_schema": "Enter your OpenAPI schema here",
|
||||
"com_ui_enter_var": "Enter {{0}}",
|
||||
"com_ui_entries": "Entries",
|
||||
"com_ui_error": "Error",
|
||||
"com_ui_error_connection": "Error connecting to server, try refreshing the page.",
|
||||
"com_ui_error_save_admin_settings": "There was an error saving your admin settings.",
|
||||
"com_ui_examples": "Examples",
|
||||
"com_ui_experimental": "Experimental Features",
|
||||
"com_ui_export_convo_modal": "Export Conversation Modal",
|
||||
"com_ui_field_required": "This field is required",
|
||||
"com_ui_filter_prompts": "Filter Prompts",
|
||||
"com_ui_filter_prompts_name": "Filter prompts by name",
|
||||
"com_ui_finance": "Finance",
|
||||
"com_ui_fork": "Fork",
|
||||
"com_ui_fork_all_target": "Include all to/from here",
|
||||
"com_ui_fork_branches": "Include related branches",
|
||||
|
@ -683,7 +623,8 @@
|
|||
"com_ui_happy_birthday": "It's my 1st birthday!",
|
||||
"com_ui_hide_qr": "Hide QR Code",
|
||||
"com_ui_host": "Host",
|
||||
"com_ui_idea": "Ideas",
|
||||
"com_ui_azure": "Azure",
|
||||
"com_ui_openai": "OpenAI",
|
||||
"com_ui_image_gen": "Image Gen",
|
||||
"com_ui_import_conversation": "Import",
|
||||
"com_ui_import_conversation_error": "There was an error importing your conversations",
|
||||
|
@ -702,30 +643,23 @@
|
|||
"com_ui_librechat_code_api_title": "Run AI Code",
|
||||
"com_ui_llm_menu": "LLM Menu",
|
||||
"com_ui_llms_available": "Available LLMs",
|
||||
"com_ui_loading": "Loading...",
|
||||
"com_ui_locked": "Locked",
|
||||
"com_ui_logo": "{{0}} Logo",
|
||||
"com_ui_manage": "Manage",
|
||||
"com_ui_max_tags": "Maximum number allowed is {{0}}, using latest values.",
|
||||
"com_ui_mention": "Mention an endpoint, assistant, or preset to quickly switch to it",
|
||||
"com_ui_min_tags": "Cannot remove more values, a minimum of {{0}} are required.",
|
||||
"com_ui_misc": "Misc.",
|
||||
"com_ui_model": "Model",
|
||||
"com_ui_model_parameters": "Model Parameters",
|
||||
"com_ui_model_save_success": "Model parameters saved successfully",
|
||||
"com_ui_more_info": "More info",
|
||||
"com_ui_more_options": "More",
|
||||
"com_ui_my_prompts": "My Prompts",
|
||||
"com_ui_name": "Name",
|
||||
"com_ui_new_chat": "New chat",
|
||||
"com_ui_new_footer": "All AI conversations in one place.",
|
||||
"com_ui_next": "Next",
|
||||
"com_ui_no": "No",
|
||||
"com_ui_no_bookmarks": "it seems like you have no bookmarks yet. Click on a chat and add a new one",
|
||||
"com_ui_no_category": "No category",
|
||||
"com_ui_no_changes": "No changes to update",
|
||||
"com_ui_no_conversation_id": "No conversation ID found",
|
||||
"com_ui_no_prompt_description": "No description found.",
|
||||
"com_ui_no_terms_content": "No terms and conditions content to display",
|
||||
"com_ui_none": "None",
|
||||
"com_ui_none_selected": "None selected",
|
||||
|
@ -735,7 +669,6 @@
|
|||
"com_ui_off": "Off",
|
||||
"com_ui_on": "On",
|
||||
"com_ui_page": "Page",
|
||||
"com_ui_pay_per_call": "All AI conversations in one place. Pay per call and not per month",
|
||||
"com_ui_prev": "Prev",
|
||||
"com_ui_preview": "Preview",
|
||||
"com_ui_privacy_policy": "Privacy policy",
|
||||
|
@ -745,7 +678,6 @@
|
|||
"com_ui_prompt_name": "Prompt Name",
|
||||
"com_ui_prompt_name_required": "Prompt Name is required",
|
||||
"com_ui_prompt_preview_not_shared": "The author has not allowed collaboration for this prompt.",
|
||||
"com_ui_prompt_shared_to_all": "This prompt is shared to all users",
|
||||
"com_ui_prompt_text": "Text",
|
||||
"com_ui_prompt_text_required": "Text is required",
|
||||
"com_ui_prompt_update_error": "There was an error updating the prompt",
|
||||
|
@ -760,7 +692,6 @@
|
|||
"com_ui_region": "Region",
|
||||
"com_ui_rename": "Rename",
|
||||
"com_ui_rename_prompt": "Rename Prompt",
|
||||
"com_ui_renaming_var": "Renaming \"{{0}}\"",
|
||||
"com_ui_requires_auth": "Requires Authentication",
|
||||
"com_ui_reset_var": "Reset {{0}}",
|
||||
"com_ui_result": "Result",
|
||||
|
@ -771,7 +702,6 @@
|
|||
"com_ui_revoke_keys": "Revoke Keys",
|
||||
"com_ui_revoke_keys_confirm": "Are you sure you want to revoke all keys?",
|
||||
"com_ui_role_select": "Role",
|
||||
"com_ui_roleplay": "Roleplay",
|
||||
"com_ui_run_code": "Run Code",
|
||||
"com_ui_run_code_error": "There was an error running the code",
|
||||
"com_ui_save": "Save",
|
||||
|
@ -780,9 +710,7 @@
|
|||
"com_ui_schema": "Schema",
|
||||
"com_ui_scope": "Scope",
|
||||
"com_ui_search": "Search",
|
||||
"com_ui_search_categories": "Search Categories",
|
||||
"com_ui_select": "Select",
|
||||
"com_ui_select_a_category": "No category selected",
|
||||
"com_ui_select_file": "Select a file",
|
||||
"com_ui_select_model": "Select a model",
|
||||
"com_ui_select_provider": "Select a provider",
|
||||
|
@ -792,27 +720,21 @@
|
|||
"com_ui_select_search_plugin": "Search plugin by name",
|
||||
"com_ui_select_search_provider": "Search provider by name",
|
||||
"com_ui_select_search_region": "Search region by name",
|
||||
"com_ui_service_http": "API Key",
|
||||
"com_ui_share": "Share",
|
||||
"com_ui_share_create_message": "Your name and any messages you add after sharing stay private.",
|
||||
"com_ui_share_created_message": "A shared link to your chat has been created. Manage previously shared chats at any time via Settings.",
|
||||
"com_ui_share_delete_error": "There was an error deleting the shared link",
|
||||
"com_ui_share_error": "There was an error sharing the chat link",
|
||||
"com_ui_share_form_description": "something needs to go here. was empty",
|
||||
"com_ui_share_link_to_chat": "Share link to chat",
|
||||
"com_ui_share_retrieve_error": "There was an error retrieving the shared links",
|
||||
"com_ui_share_to_all_users": "Share to all users",
|
||||
"com_ui_share_update_message": "Your name, custom instructions, and any messages you add after sharing stay private.",
|
||||
"com_ui_share_updated_message": "A shared link to your chat has been updated. Manage previously shared chats at any time via Settings.",
|
||||
"com_ui_share_var": "Share {{0}}",
|
||||
"com_ui_shared_link_bulk_delete_success": "Successfully deleted shared links",
|
||||
"com_ui_shared_link_delete_success": "Successfully deleted shared link",
|
||||
"com_ui_shared_link_not_found": "Shared link not found",
|
||||
"com_ui_shared_prompts": "Shared Prompts",
|
||||
"com_ui_shop": "Shopping",
|
||||
"com_ui_show_all": "Show All",
|
||||
"com_ui_show_qr": "Show QR Code",
|
||||
"com_ui_showing": "Showing",
|
||||
"com_ui_sign_in_to_domain": "Sign-in to {{0}}",
|
||||
"com_ui_simple": "Simple",
|
||||
"com_ui_size": "Size",
|
||||
|
@ -822,18 +744,14 @@
|
|||
"com_ui_stop": "Stop",
|
||||
"com_ui_storage": "Storage",
|
||||
"com_ui_submit": "Submit",
|
||||
"com_ui_success": "Success",
|
||||
"com_ui_teach_or_explain": "Learning",
|
||||
"com_ui_temporary_chat": "Temporary Chat",
|
||||
"com_ui_terms_and_conditions": "Terms and Conditions",
|
||||
"com_ui_terms_of_service": "Terms of service",
|
||||
"com_ui_thinking": "Thinking...",
|
||||
"com_ui_thoughts": "Thoughts",
|
||||
"com_ui_title": "Title",
|
||||
"com_ui_token_exchange_method": "Token Exchange Method",
|
||||
"com_ui_token_url": "Token URL",
|
||||
"com_ui_tools": "Tools",
|
||||
"com_ui_travel": "Travel",
|
||||
"com_ui_unarchive": "Unarchive",
|
||||
"com_ui_unarchive_error": "Failed to unarchive conversation",
|
||||
"com_ui_unknown": "Unknown",
|
||||
|
@ -857,9 +775,14 @@
|
|||
"com_ui_version_var": "Version {{0}}",
|
||||
"com_ui_versions": "Versions",
|
||||
"com_ui_view_source": "View source chat",
|
||||
"com_ui_write": "Writing",
|
||||
"com_ui_yes": "Yes",
|
||||
"com_ui_zoom": "Zoom",
|
||||
"com_user_message": "You",
|
||||
"com_warning_resubmit_unsupported": "Resubmitting the AI message is not supported for this endpoint."
|
||||
"com_warning_resubmit_unsupported": "Resubmitting the AI message is not supported for this endpoint.",
|
||||
"com_ui_no_data": "something needs to go here. was empty",
|
||||
"com_files_table": "something needs to go here. was empty",
|
||||
"com_ui_global_group": "something needs to go here. was empty",
|
||||
"com_ui_no_valid_items": "something needs to go here. was empty",
|
||||
"chat_direction_left_to_right": "something needs to go here. was empty",
|
||||
"chat_direction_right_to_left": "something needs to go here. was empty"
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@ import {
|
|||
} from '~/components/ui';
|
||||
import { useLocalize, useCustomLink, useAuthContext } from '~/hooks';
|
||||
import AdvancedSwitch from '~/components/Prompts/AdvancedSwitch';
|
||||
import { RightPanel } from '../../components/Prompts/RightPanel';
|
||||
// import { RightPanel } from '../../components/Prompts/RightPanel';
|
||||
import AdminSettings from '~/components/Prompts/AdminSettings';
|
||||
import { useDashboardContext } from '~/Providers';
|
||||
import { PromptsEditorMode } from '~/common';
|
||||
// import { PromptsEditorMode } from '~/common';
|
||||
import store from '~/store';
|
||||
|
||||
const promptsPathPattern = /prompts\/(?!new(?:\/|$)).*$/;
|
||||
|
|
|
@ -3,9 +3,9 @@ import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
|||
import type { TStartupConfig } from 'librechat-data-provider';
|
||||
import { useGetStartupConfig } from '~/data-provider';
|
||||
import AuthLayout from '~/components/Auth/AuthLayout';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { TranslationKeys, useLocalize } from '~/hooks';
|
||||
|
||||
const headerMap = {
|
||||
const headerMap: Record<string, TranslationKeys> = {
|
||||
'/login': 'com_auth_welcome_back',
|
||||
'/register': 'com_auth_create_account',
|
||||
'/forgot-password': 'com_auth_reset_password',
|
||||
|
@ -13,8 +13,8 @@ const headerMap = {
|
|||
};
|
||||
|
||||
export default function StartupLayout({ isAuthenticated }: { isAuthenticated?: boolean }) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [headerText, setHeaderText] = useState<string | null>(null);
|
||||
const [error, setError] = useState<TranslationKeys | null>(null);
|
||||
const [headerText, setHeaderText] = useState<TranslationKeys | null>(null);
|
||||
const [startupConfig, setStartupConfig] = useState<TStartupConfig | null>(null);
|
||||
const {
|
||||
data,
|
||||
|
|
|
@ -8,6 +8,7 @@ import tsParser from '@typescript-eslint/parser';
|
|||
import importPlugin from 'eslint-plugin-import';
|
||||
import { FlatCompat } from '@eslint/eslintrc';
|
||||
import jsxA11Y from 'eslint-plugin-jsx-a11y';
|
||||
import i18next from 'eslint-plugin-i18next';
|
||||
import react from 'eslint-plugin-react';
|
||||
import jest from 'eslint-plugin-jest';
|
||||
import globals from 'globals';
|
||||
|
@ -58,6 +59,7 @@ export default [
|
|||
import: importPlugin,
|
||||
'jsx-a11y': fixupPluginRules(jsxA11Y),
|
||||
'import/parsers': tsParser,
|
||||
i18next,
|
||||
// perfectionist,
|
||||
},
|
||||
|
||||
|
@ -284,6 +286,13 @@ export default [
|
|||
},
|
||||
},
|
||||
rules: {
|
||||
// i18n
|
||||
'i18next/no-literal-string': [
|
||||
'error', {
|
||||
mode: 'jsx-text-only',
|
||||
'should-validate-template': true,
|
||||
}],
|
||||
//
|
||||
'@typescript-eslint/no-unused-expressions': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
|
|
33
package-lock.json
generated
33
package-lock.json
generated
|
@ -22,9 +22,10 @@
|
|||
"@playwright/test": "^1.50.1",
|
||||
"@types/react-virtualized": "^9.22.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^9.20.0",
|
||||
"eslint": "^9.20.1",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-import-resolver-typescript": "^3.7.0",
|
||||
"eslint-plugin-i18next": "^6.1.1",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jest": "^28.11.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
|
@ -20586,9 +20587,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.20.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.0.tgz",
|
||||
"integrity": "sha512-aL4F8167Hg4IvsW89ejnpTwx+B/UQRzJPGgbIOl+4XqffWsahVVsLEWoZvnrVuwpWmnRd7XeXmQI1zlKcFDteA==",
|
||||
"version": "9.20.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz",
|
||||
"integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
@ -20742,6 +20743,20 @@
|
|||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-i18next": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-i18next/-/eslint-plugin-i18next-6.1.1.tgz",
|
||||
"integrity": "sha512-/Vy6BfX44njxpRnbJm7bbph0KaNJF2eillqN5W+u03hHuxmh9BjtjdPSrI9HPtyoEbG4j5nBn9gXm/dg99mz3Q==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"requireindex": "~1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import": {
|
||||
"version": "2.31.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz",
|
||||
|
@ -32731,6 +32746,16 @@
|
|||
"integrity": "sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/requireindex": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz",
|
||||
"integrity": "sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.5"
|
||||
}
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
|
|
|
@ -88,9 +88,10 @@
|
|||
"@playwright/test": "^1.50.1",
|
||||
"@types/react-virtualized": "^9.22.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^9.20.0",
|
||||
"eslint": "^9.20.1",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-import-resolver-typescript": "^3.7.0",
|
||||
"eslint-plugin-i18next": "^6.1.1",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jest": "^28.11.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
|
|
|
@ -1208,7 +1208,9 @@ export enum ForkOptions {
|
|||
/** Key for including branches */
|
||||
INCLUDE_BRANCHES = 'includeBranches',
|
||||
/** Key for target level fork (default) */
|
||||
TARGET_LEVEL = '',
|
||||
TARGET_LEVEL = 'targetLevel',
|
||||
/** Default option */
|
||||
DEFAULT = 'default',
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue