Skip to content

Commit

Permalink
Add localization support for endpoint pages components (#667)
Browse files Browse the repository at this point in the history
* init localization

* Update defaul to en

* Fix merge issue and import path.

* Set default to en

* Change jsx to tsx

* Update the password max length string.

* Remove languageContext as using the recoil instead.

* Add localization to component endpoints pages

* Revert default to en after testing.

* Update LoginForm.tsx

* Fix translation.

* Make lint happy
  • Loading branch information
NoahDragon authored Jul 22, 2023
1 parent 4148c6d commit b642739
Show file tree
Hide file tree
Showing 15 changed files with 212 additions and 67 deletions.
22 changes: 13 additions & 9 deletions client/src/components/Endpoints/BingAI/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import SelectDropDown from '../../ui/SelectDropDown';
import { cn } from '~/utils/';
import useDebounce from '~/hooks/useDebounce';
import { useUpdateTokenCountMutation } from '@librechat/data-provider';
import { useRecoilValue } from 'recoil';
import store from '~/store';
import { localize } from '~/localization/Translation';

const defaultTextProps =
'rounded-md border border-gray-200 focus:border-slate-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
Expand All @@ -20,6 +23,7 @@ function Settings(props) {
const setToneStyle = (value) => setOption('toneStyle')(value.toLowerCase());
const debouncedContext = useDebounce(context, 250);
const updateTokenCountMutation = useUpdateTokenCountMutation();
const lang = useRecoilValue(store.lang);

useEffect(() => {
if (!debouncedContext || debouncedContext.trim() === '') {
Expand Down Expand Up @@ -48,7 +52,7 @@ function Settings(props) {
<div className="col-span-1 flex flex-col items-center justify-start gap-6">
<div className="grid w-full items-center gap-2">
<Label htmlFor="toneStyle-dropdown" className="text-left text-sm font-medium">
Tone Style <small className="opacity-40">(default: creative)</small>
{localize(lang, 'com_endpoint_tone_style')} <small className="opacity-40">({localize(lang, 'com_endpoint_default_creative')})</small>
</Label>
<SelectDropDown
id="toneStyle-dropdown"
Expand All @@ -66,26 +70,26 @@ function Settings(props) {
</div>
<div className="grid w-full items-center gap-2">
<Label htmlFor="context" className="text-left text-sm font-medium">
Context <small className="opacity-40">(default: blank)</small>
{localize(lang, 'com_endpoint_context')} <small className="opacity-40">({localize(lang, 'com_endpoint_default_blank')})</small>
</Label>
<TextareaAutosize
id="context"
disabled={readonly}
value={context || ''}
onChange={(e) => setContext(e.target.value || null)}
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"
placeholder={localize(lang, 'com_endpoint_bing_context_placeholder')}
className={cn(
defaultTextProps,
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2',
)}
/>
<small className="mb-5 text-black dark:text-white">{`Token count: ${tokenCount}`}</small>
<small className="mb-5 text-black dark:text-white">{`${localize(lang, 'com_endpoint_token_count')}: ${tokenCount}`}</small>
</div>
</div>
<div className="col-span-1 flex flex-col items-center justify-start gap-6">
<div className="grid w-full items-center gap-2">
<Label htmlFor="jailbreak" className="text-left text-sm font-medium">
Enable Sydney <small className="opacity-40">(default: false)</small>
{localize(lang, 'com_endpoint_bing_enable_sydney')} <small className="opacity-40">({localize(lang, 'com_endpoint_default_false')})</small>
</Label>
<div className="flex h-[40px] w-full items-center space-x-3">
<Checkbox
Expand All @@ -99,7 +103,7 @@ function Settings(props) {
htmlFor="jailbreak"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 dark:text-gray-50"
>
Jailbreak <small>To enable Sydney</small>
{localize(lang, 'com_endpoint_bing_jailbreak')} <small>{localize(lang, 'com_endpoint_bing_to_enable_sydney')}</small>
</label>
</div>
</div>
Expand All @@ -116,17 +120,17 @@ function Settings(props) {
className="text-blue-500 transition-colors duration-200 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-500"
rel="noreferrer"
>
System Message
{localize(lang, 'com_endpoint_system_message')}
</a>{' '}
<small className="opacity-40 dark:text-gray-50">(default: blank)</small>
<small className="opacity-40 dark:text-gray-50">( {localize(lang, 'com_endpoint_default_blank')})</small>
</Label>

<TextareaAutosize
id="systemMessage"
disabled={readonly}
value={systemMessage || ''}
onChange={(e) => setSystemMessage(e.target.value || null)}
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."
placeholder={localize(lang, 'com_endpoint_bing_system_message_placeholder')}
className={cn(
defaultTextProps,
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2 placeholder:text-red-400',
Expand Down
24 changes: 18 additions & 6 deletions client/src/components/Endpoints/EditPresetDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import {
} from '~/components/';
import { cn } from '~/utils/';
import cleanupPreset from '~/utils/cleanupPreset';
import { localize } from '~/localization/Translation';

import store from '~/store';

const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
const lang = useRecoilValue(store.lang);
const [preset, setPreset] = useState(_preset);
const setPresets = useSetRecoilState(store.presets);
const [showExamples, setShowExamples] = useState(false);
Expand Down Expand Up @@ -174,13 +176,13 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
<div className="grid w-full gap-6 sm:grid-cols-2">
<div className="col-span-1 flex flex-col items-start justify-start gap-2">
<Label htmlFor="chatGptLabel" className="text-left text-sm font-medium">
Preset Name
{localize(lang, 'com_endpoint_preset_name')}
</Label>
<Input
id="chatGptLabel"
value={preset?.title || ''}
onChange={(e) => setOption('title')(e.target.value || '')}
placeholder="Set a custom name, in case you can find this preset"
placeholder={localize(lang, 'com_endpoint_set_custom_name')}
className={cn(
defaultTextProps,
'flex h-10 max-h-10 w-full resize-none px-3 py-2 focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0',
Expand All @@ -189,7 +191,7 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
</div>
<div className="col-span-1 flex flex-col items-start justify-start gap-2">
<Label htmlFor="endpoint" className="text-left text-sm font-medium">
Endpoint
{localize(lang, 'com_endpoint')}
</Label>
<Dropdown
id="endpoint"
Expand All @@ -209,7 +211,10 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
onClick={triggerExamples}
>
<MessagesSquared className="mr-1 w-[14px]" />
{(showExamples ? 'Hide' : 'Show') + ' Examples'}
{(showExamples
? localize(lang, 'com_endpoint_hide')
: localize(lang, 'com_endpoint_show')) +
localize(lang, 'com_endpoint_examples')}
</Button>
)}
{preset?.endpoint === 'gptPlugins' && (
Expand All @@ -220,6 +225,13 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
>
<GPTIcon className="mr-1 mt-[2px] w-[14px]" size={14} />
{`Show ${showAgentSettings ? 'Completion' : 'Agent'} Settings`}
{localize(
lang,
'com_endpoint_show_what_settings',
showAgentSettings
? localize(lang, 'com_endpoint_completion')
: localize(lang, 'com_endpoint_agent'),
)}
</Button>
)}
</div>
Expand Down Expand Up @@ -261,14 +273,14 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
onClick={submitPreset}
className="dark:hover:gray-400 border-gray-700 bg-green-600 text-white hover:bg-green-700 dark:hover:bg-green-800"
>
Save
{localize(lang, 'com_endpoint_save')}
</DialogClose>
</>
}
leftButtons={
<>
<DialogButton onClick={exportPreset} className="dark:hover:gray-400 border-gray-700">
Export
{localize(lang, 'com_endpoint_export')}
</DialogButton>
</>
}
Expand Down
6 changes: 4 additions & 2 deletions client/src/components/Endpoints/EndpointOptionsDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import { alternateName } from '~/utils';
import Settings from './Settings';

import store from '~/store';
import { localize } from '~/localization/Translation';

// A preset dialog to show readonly preset values.
const EndpointOptionsDialog = ({ open, onOpenChange, preset: _preset, title }) => {
const [preset, setPreset] = useState(_preset);
const [saveAsDialogShow, setSaveAsDialogShow] = useState(false);
const endpointsConfig = useRecoilValue(store.endpointsConfig);
const endpointName = alternateName[preset?.endpoint] ?? 'Endpoint';
const lang = useRecoilValue(store.lang);

const setOption = (param) => (newValue) => {
let update = {};
Expand Down Expand Up @@ -61,14 +63,14 @@ const EndpointOptionsDialog = ({ open, onOpenChange, preset: _preset, title }) =
onClick={saveAsPreset}
className="dark:hover:gray-400 border-gray-700 bg-green-600 text-white hover:bg-green-700 dark:hover:bg-green-800"
>
Save As Preset
{localize(lang, 'com_endpoint_save_as_preset')}
</DialogButton>
</>
}
leftButtons={
<>
<DialogButton onClick={exportPreset} className="dark:hover:gray-400 border-gray-700">
Export
{localize(lang, 'com_endpoint_export')}
</DialogButton>
</>
}
Expand Down
7 changes: 6 additions & 1 deletion client/src/components/Endpoints/EndpointOptionsPopover.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import CrossIcon from '../svg/CrossIcon';
import { Save } from 'lucide-react';
import { cn } from '~/utils/';

import store from '~/store';
import { useRecoilValue } from 'recoil';
import { localize } from '~/localization/Translation';

function EndpointOptionsPopover({
content,
visible,
saveAsPreset,
switchToSimpleMode,
additionalButton = null,
}) {
const lang = useRecoilValue(store.lang);
const cardStyle =
'shadow-md rounded-md min-w-[75px] font-normal bg-white border-black/10 border dark:bg-gray-700 text-black dark:text-white';

Expand All @@ -37,7 +42,7 @@ function EndpointOptionsPopover({
onClick={saveAsPreset}
>
<Save className="mr-1 w-[14px]" />
Save as preset
{localize(lang, 'com_endpoint_save_as_preset')}
</Button>
{additionalButton && (
<Button
Expand Down
10 changes: 8 additions & 2 deletions client/src/components/Endpoints/Google/Examples.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ import { Button } from '~/components/ui/Button.tsx';
import { Label } from '~/components/ui/Label.tsx';
import { Plus, Minus } from 'lucide-react';
import { cn } from '~/utils/';
import { useRecoilValue } from 'recoil';
import store from '~/store';
import { localize } from '~/localization/Translation';

const defaultTextProps =
'rounded-md border border-gray-200 focus:border-slate-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';

function Examples({ readonly, examples, setExample, addExample, removeExample, edit = false }) {
const maxHeight = edit ? 'max-h-[233px]' : 'max-h-[350px]';
const lang = useRecoilValue(store.lang);

return (
<>
<div className={`${maxHeight} overflow-y-auto`}>
Expand All @@ -23,7 +29,7 @@ function Examples({ readonly, examples, setExample, addExample, removeExample, e
>
<div className="grid w-full items-center gap-2">
<Label htmlFor={`input-${idx}`} className="text-left text-sm font-medium">
Input <small className="opacity-40">(default: blank)</small>
{localize(lang, 'com_ui_input')} <small className="opacity-40">({localize(lang, 'com_endpoint_default_blank')})</small>
</Label>
<TextareaAutosize
id={`input-${idx}`}
Expand All @@ -47,7 +53,7 @@ function Examples({ readonly, examples, setExample, addExample, removeExample, e
>
<div className="grid w-full items-center gap-2">
<Label htmlFor={`output-${idx}`} className="text-left text-sm font-medium">
Output <small className="opacity-40">(default: blank)</small>
{localize(lang, 'com_endpoint_output')} <small className="opacity-40">({localize(lang, 'com_endpoint_default_blank')})</small>
</Label>
<TextareaAutosize
id={`output-${idx}`}
Expand Down
15 changes: 9 additions & 6 deletions client/src/components/Endpoints/Google/OptionHover.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import React from 'react';
import { HoverCardPortal, HoverCardContent } from '~/components/ui/HoverCard.tsx';
import { useRecoilValue } from 'recoil';
import store from '~/store';
import { localize } from '~/localization/Translation';

const types = {
temp: 'Higher values = more random, while lower values = more focused and deterministic. We recommend altering this or Top P but not both.',
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.',
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).',
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.',
temp: 'com_endpoint_google_temp',
topp: 'com_endpoint_google_topp',
topk: 'com_endpoint_google_topk',
maxoutputtokens: 'com_endpoint_google_maxoutputtokens',
};

function OptionHover({ type, side }) {
// const options = {};
// if (type === 'pres') {
// options.sideOffset = 45;
// }
const lang = useRecoilValue(store.lang);

return (
<HoverCardPortal>
Expand All @@ -23,7 +26,7 @@ function OptionHover({ type, side }) {
// {...options}
>
<div className="space-y-2">
<p className="text-sm text-gray-600 dark:text-gray-300">{types[type]}</p>
<p className="text-sm text-gray-600 dark:text-gray-300">{localize(lang, types[type])}</p>
</div>
</HoverCardContent>
</HoverCardPortal>
Expand Down
Loading

0 comments on commit b642739

Please sign in to comment.