mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-21 19:00:13 +01:00
feat: auto detect language (#947)
* added auto-detect language * fix(TranslationSelect) now saving the selected language between sessions * fix(LangSelector.spec) * fix(conflict) * fix(Swedish) sv-SE
This commit is contained in:
parent
2419af8748
commit
b48c618f32
12 changed files with 329 additions and 328 deletions
|
|
@ -36,7 +36,7 @@ export default function Settings({ open, onOpenChange }: TDialogProps) {
|
|||
>
|
||||
<Tabs.Trigger
|
||||
className={cn(
|
||||
'group flex items-center justify-start gap-2 rounded-md px-2 py-1.5 text-sm radix-state-active:bg-gray-800 radix-state-active:text-white',
|
||||
'group flex items-center justify-start gap-2 rounded-md px-2 py-1.5 text-sm text-gray-500 radix-state-active:bg-gray-800 radix-state-active:text-white',
|
||||
isSmallScreen
|
||||
? 'flex-1 items-center justify-center text-sm dark:text-gray-500 dark:radix-state-active:text-white'
|
||||
: '',
|
||||
|
|
@ -48,7 +48,7 @@ export default function Settings({ open, onOpenChange }: TDialogProps) {
|
|||
</Tabs.Trigger>
|
||||
<Tabs.Trigger
|
||||
className={cn(
|
||||
'group flex items-center justify-start gap-2 rounded-md px-2 py-1.5 text-sm radix-state-active:bg-gray-800 radix-state-active:text-white',
|
||||
'group flex items-center justify-start gap-2 rounded-md px-2 py-1.5 text-sm text-gray-500 radix-state-active:bg-gray-800 radix-state-active:text-white',
|
||||
isSmallScreen
|
||||
? 'flex-1 items-center justify-center text-sm dark:text-gray-500 dark:radix-state-active:text-white'
|
||||
: '',
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
import type { TDangerButtonProps } from '~/common';
|
||||
import DangerButton from './DangerButton';
|
||||
import store from '~/store';
|
||||
import useLocalStorage from '~/hooks/useLocalStorage';
|
||||
|
||||
export const ThemeSelector = ({
|
||||
theme,
|
||||
|
|
@ -82,17 +83,18 @@ export const LangSelector = ({
|
|||
onChange={(e) => onChange(e.target.value)}
|
||||
value={langcode}
|
||||
>
|
||||
<option value="en">{localize('com_nav_lang_english')}</option>
|
||||
<option value="cn">{localize('com_nav_lang_chinese')}</option>
|
||||
<option value="de">{localize('com_nav_lang_german')}</option>
|
||||
<option value="es">{localize('com_nav_lang_spanish')}</option>
|
||||
<option value="fr">{localize('com_nav_lang_french')}</option>
|
||||
<option value="it">{localize('com_nav_lang_italian')}</option>
|
||||
<option value="pl">{localize('com_nav_lang_polish')}</option>
|
||||
<option value="br">{localize('com_nav_lang_brazilian_portuguese')}</option>
|
||||
<option value="ru">{localize('com_nav_lang_russian')}</option>
|
||||
<option value="jp">{localize('com_nav_lang_japanese')}</option>
|
||||
<option value="sv">{localize('com_nav_lang_swedish')}</option>
|
||||
<option value="auto">{localize('com_nav_lang_auto')}</option>
|
||||
<option value="en-US">{localize('com_nav_lang_english')}</option>
|
||||
<option value="zh-CN">{localize('com_nav_lang_chinese')}</option>
|
||||
<option value="de-DE">{localize('com_nav_lang_german')}</option>
|
||||
<option value="es-ES">{localize('com_nav_lang_spanish')}</option>
|
||||
<option value="fr-FR">{localize('com_nav_lang_french')}</option>
|
||||
<option value="it-IT">{localize('com_nav_lang_italian')}</option>
|
||||
<option value="pl-PL">{localize('com_nav_lang_polish')}</option>
|
||||
<option value="pt-BR">{localize('com_nav_lang_brazilian_portuguese')}</option>
|
||||
<option value="ru-RU">{localize('com_nav_lang_russian')}</option>
|
||||
<option value="ja-JP">{localize('com_nav_lang_japanese')}</option>
|
||||
<option value="sv-SE">{localize('com_nav_lang_swedish')}</option>
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -103,6 +105,7 @@ function General() {
|
|||
const clearConvosMutation = useClearConversationsMutation();
|
||||
const [confirmClear, setConfirmClear] = useState(false);
|
||||
const [langcode, setLangcode] = useRecoilState(store.lang);
|
||||
const [selectedLang, setSelectedLang] = useLocalStorage('selectedLang', langcode);
|
||||
const { newConversation } = useConversation();
|
||||
const { refreshConversations } = useConversations();
|
||||
|
||||
|
|
@ -135,9 +138,17 @@ function General() {
|
|||
|
||||
const changeLang = useCallback(
|
||||
(value: string) => {
|
||||
setLangcode(value);
|
||||
setSelectedLang(value);
|
||||
if (value === 'auto') {
|
||||
const userLang = navigator.language || navigator.languages[0];
|
||||
setLangcode(userLang);
|
||||
localStorage.setItem('lang', userLang);
|
||||
} else {
|
||||
setLangcode(value);
|
||||
localStorage.setItem('lang', value);
|
||||
}
|
||||
},
|
||||
[setLangcode],
|
||||
[setLangcode, setSelectedLang],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
@ -152,7 +163,7 @@ function General() {
|
|||
<ThemeSelector theme={theme} onChange={changeTheme} />
|
||||
</div>
|
||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
||||
<LangSelector langcode={langcode} onChange={changeLang} />
|
||||
<LangSelector langcode={selectedLang} onChange={changeLang} />
|
||||
</div>
|
||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
||||
<ClearChatsButton
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ describe('LangSelector', () => {
|
|||
it('renders correctly', () => {
|
||||
const { getByText, getByDisplayValue } = render(
|
||||
<RecoilRoot>
|
||||
<LangSelector langcode="en" onChange={mockOnChange} />
|
||||
<LangSelector langcode="en-US" onChange={mockOnChange} />
|
||||
</RecoilRoot>,
|
||||
);
|
||||
|
||||
|
|
@ -26,12 +26,12 @@ describe('LangSelector', () => {
|
|||
it('calls onChange when the select value changes', () => {
|
||||
const { getByDisplayValue } = render(
|
||||
<RecoilRoot>
|
||||
<LangSelector langcode="en" onChange={mockOnChange} />
|
||||
<LangSelector langcode="en-US" onChange={mockOnChange} />
|
||||
</RecoilRoot>,
|
||||
);
|
||||
|
||||
fireEvent.change(getByDisplayValue('English'), { target: { value: 'it' } });
|
||||
fireEvent.change(getByDisplayValue('English'), { target: { value: 'it-IT' } });
|
||||
|
||||
expect(mockOnChange).toHaveBeenCalledWith('it');
|
||||
expect(mockOnChange).toHaveBeenCalledWith('it-IT');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue