diff --git a/apps/ui-tars/src/renderer/src/components/AlertDialog/delSessionDialog.tsx b/apps/ui-tars/src/renderer/src/components/AlertDialog/delSessionDialog.tsx index 57959c187c..b70c6b5ff9 100644 --- a/apps/ui-tars/src/renderer/src/components/AlertDialog/delSessionDialog.tsx +++ b/apps/ui-tars/src/renderer/src/components/AlertDialog/delSessionDialog.tsx @@ -12,6 +12,7 @@ import { AlertDialogHeader, AlertDialogTitle, } from '@renderer/components/ui/alert-dialog'; +import { useI18n } from '../../i18n'; interface DeleteSessionDialogProps { open: boolean; @@ -24,23 +25,24 @@ export function DeleteSessionDialog({ onOpenChange, onConfirm, }: DeleteSessionDialogProps) { + const { t } = useI18n(); + return ( - Delete Session + {t('deleteSession')} - The current session is running. Navigating away will forcibly stop - the session. Do you still want to proceed? + {t('deleteSessionDescription')} - Cancel + {t('cancel')} - Delete + {t('delete')} diff --git a/apps/ui-tars/src/renderer/src/components/AlertDialog/freeTrialDialog.tsx b/apps/ui-tars/src/renderer/src/components/AlertDialog/freeTrialDialog.tsx index 0554d6d578..f452e9284e 100644 --- a/apps/ui-tars/src/renderer/src/components/AlertDialog/freeTrialDialog.tsx +++ b/apps/ui-tars/src/renderer/src/components/AlertDialog/freeTrialDialog.tsx @@ -15,6 +15,7 @@ import { } from '@renderer/components/ui/alert-dialog'; import { Checkbox } from '@renderer/components/ui/checkbox'; import { Label } from '@renderer/components/ui/label'; +import { useI18n } from '../../i18n'; interface FreeTrialDialog { open: boolean; @@ -24,6 +25,7 @@ interface FreeTrialDialog { export const FreeTrialDialog = memo( ({ open, onOpenChange, onConfirm }: FreeTrialDialog) => { + const { t } = useI18n(); const [dontShowAgain, setDontShowAgain] = useState(false); const onCheck = (status: boolean) => { @@ -41,41 +43,29 @@ export const FreeTrialDialog = memo( - Free Trial Service Agreement + {t('freeTrialAgreement')}
-

- As part of our research, we offer a 30-minute free trial of our - cloud service powered by Volcano Engine, where you can - experience UI-TARS with remote computer and browser operations - without purchasing model service and computing resources. -

-

- - By agreeing to use this service, your data will be transmitted - to the servers. Please note that. - {' '} - In compliance with relevant regulations, you should avoid - entering any sensitive personal information. All records on the - servers will be exclusively used for academic research purposes - and will not be utilized for any other activities. -

+

{t('freeTrialIntro')}

- Thank you for your support of the UI-TARS research project! + {t('freeTrialDataNotice')} {t('freeTrialDataCompliance')}

+

{t('freeTrialThanks')}

- +
- Cancel - Agree + {t('cancel')} + + {t('agree')} +
diff --git a/apps/ui-tars/src/renderer/src/components/AlertDialog/navDialog.tsx b/apps/ui-tars/src/renderer/src/components/AlertDialog/navDialog.tsx index 1c33a8c45f..85b1b832fe 100644 --- a/apps/ui-tars/src/renderer/src/components/AlertDialog/navDialog.tsx +++ b/apps/ui-tars/src/renderer/src/components/AlertDialog/navDialog.tsx @@ -14,6 +14,7 @@ import { AlertDialogTitle, } from '@renderer/components/ui/alert-dialog'; import { memo } from 'react'; +import { useI18n } from '../../i18n'; interface NavDialogStore { isOpen: boolean; @@ -37,23 +38,24 @@ export const useNavDialog = create((set) => ({ export const NavDialog = memo( ({ open, onOpenChange, onConfirm }: NavDialogProps) => { + const { t } = useI18n(); + return ( - Navigation Alert + {t('navigationAlert')} - The current instance is running. Navigating away will forcibly - stop the instance. Do you still want to proceed? + {t('navigationAlertDescription')} - Cancel + {t('cancel')} - Confirm + {t('confirm')} diff --git a/apps/ui-tars/src/renderer/src/components/AlertDialog/terminateDialog.tsx b/apps/ui-tars/src/renderer/src/components/AlertDialog/terminateDialog.tsx index d822d362b3..2aa7ca79b8 100644 --- a/apps/ui-tars/src/renderer/src/components/AlertDialog/terminateDialog.tsx +++ b/apps/ui-tars/src/renderer/src/components/AlertDialog/terminateDialog.tsx @@ -13,6 +13,7 @@ import { AlertDialogHeader, AlertDialogTitle, } from '@renderer/components/ui/alert-dialog'; +import { useI18n } from '../../i18n'; interface TerminateDialogProps { open: boolean; @@ -22,25 +23,24 @@ interface TerminateDialogProps { export const TerminateDialog = memo( ({ open, onOpenChange, onConfirm }: TerminateDialogProps) => { + const { t } = useI18n(); + return ( - - Terminate the current instance ? - + {t('terminateCurrentInstance')} - After termination, the current remote instance will be reclaimed, - and the task will be paused + {t('terminateDescription')} - Cancel + {t('cancel')} - Terminate + {t('terminate')} diff --git a/apps/ui-tars/src/renderer/src/components/ChatInput/index.tsx b/apps/ui-tars/src/renderer/src/components/ChatInput/index.tsx index 3958821fa9..a5849653de 100644 --- a/apps/ui-tars/src/renderer/src/components/ChatInput/index.tsx +++ b/apps/ui-tars/src/renderer/src/components/ChatInput/index.tsx @@ -26,6 +26,7 @@ import { useSession } from '@renderer/hooks/useSession'; import { Operator } from '@main/store/types'; import { useSetting } from '../../hooks/useSetting'; +import { useI18n } from '../../i18n'; const ChatInput = ({ operator, @@ -38,6 +39,7 @@ const ChatInput = ({ disabled: boolean; checkBeforeRun?: () => Promise; }) => { + const { t } = useI18n(); const { status, instructions: savedInstructions, @@ -187,10 +189,7 @@ const ChatInput = ({ -

- send last instructions when you done for ui-tars's - 'CALL_USER' -

+

{t('callUserTooltip')}

@@ -221,7 +220,7 @@ const ChatInput = ({ ? `${savedInstructions}` : running && lastHumanMessage && messages?.length > 1 ? lastHumanMessage - : 'What can I do for you today?' + : t('chatPlaceholder') } className="min-h-[120px] rounded-2xl resize-none px-4 pb-16" // 调整内边距 value={localInstructions} diff --git a/apps/ui-tars/src/renderer/src/components/Settings/category/chat.tsx b/apps/ui-tars/src/renderer/src/components/Settings/category/chat.tsx index 3a64eed484..681f50719e 100644 --- a/apps/ui-tars/src/renderer/src/components/Settings/category/chat.tsx +++ b/apps/ui-tars/src/renderer/src/components/Settings/category/chat.tsx @@ -25,6 +25,7 @@ import { SelectValue, } from '@renderer/components/ui/select'; import { Input } from '@renderer/components/ui/input'; +import { useI18n } from '../../../i18n'; const formSchema = z.object({ language: z.enum(['en', 'zh']), @@ -33,6 +34,7 @@ const formSchema = z.object({ }); export function ChatSettings() { + const { t } = useI18n(); const { settings, updateSetting } = useSetting(); const form = useForm>({ @@ -97,17 +99,15 @@ export function ChatSettings() { render={({ field }) => { return ( - Language - - Control the language used in LLM conversations - + {t('language')} + {t('languageDescription')} @@ -121,10 +121,8 @@ export function ChatSettings() { // console.log('field', field); return ( - Max Loop - - Enter a number between 25-200 - + {t('maxLoop')} + {t('maxLoopDescription')} ( - Loop Wait Time (ms) - Enter a number between 0-3000 + {t('loopWaitTime')} + {t('loopWaitDescription')} field.onChange(Number(e.target.value))} diff --git a/apps/ui-tars/src/renderer/src/components/Settings/category/general.tsx b/apps/ui-tars/src/renderer/src/components/Settings/category/general.tsx index 404cd70f31..445dfaa65f 100644 --- a/apps/ui-tars/src/renderer/src/components/Settings/category/general.tsx +++ b/apps/ui-tars/src/renderer/src/components/Settings/category/general.tsx @@ -5,8 +5,10 @@ import { api } from '@/renderer/src/api'; import { toast } from 'sonner'; import { REPO_OWNER, REPO_NAME } from '@main/shared/constants'; +import { useI18n } from '../../../i18n'; export const GeneralSettings = () => { + const { t } = useI18n(); const [updateLoading, setUpdateLoading] = useState(false); const [updateDetail, setUpdateDetail] = useState<{ currentVersion: string; @@ -28,10 +30,12 @@ export const GeneralSettings = () => { }); return; } else if (!detail.isPackaged) { - toast.info('Unpackaged version does not support update check!'); + toast.info(t('unpackagedNoUpdate')); } else { - toast.success('No update available', { - description: `current version: ${detail.currentVersion} is the latest version`, + toast.success(t('noUpdateAvailable'), { + description: t('currentVersionLatest', { + version: detail.currentVersion, + }), position: 'top-right', richColors: true, }); @@ -54,7 +58,7 @@ export const GeneralSettings = () => { - {updateLoading ? 'Checking...' : 'Check Updates'} + {updateLoading ? t('checking') : t('checkUpdates')} {updateDetail?.version && (
@@ -63,7 +67,7 @@ export const GeneralSettings = () => { )} {updateDetail?.link && (
- Release Notes:{' '} + {t('releaseNotes')}{' '} >({ @@ -82,11 +84,11 @@ export function LocalBrowserSettings() { name="searchEngineForBrowser" render={({ field }) => ( - Default Search Engine: + {t('defaultSearchEngine')} ( - UTIO Base URL + {t('utioBaseUrl')} ({ @@ -274,7 +274,7 @@ export function VLMSettings({
{!isRemoteAutoUpdatedPreset && ( )} {isRemoteAutoUpdatedPreset && ( @@ -293,14 +293,14 @@ export function VLMSettings({ render={({ field }) => { return ( - VLM Provider + {t('vlmProvider')} @@ -340,13 +340,13 @@ export function VLMSettings({ name="vlmApiKey" render={({ field }) => ( - VLM API Key + {t('vlmApiKey')}
@@ -375,11 +375,11 @@ export function VLMSettings({ name="vlmModelName" render={({ field }) => ( - VLM Model Name + {t('vlmModelName')} @@ -392,6 +392,7 @@ export function VLMSettings({ ( - Use Responses API + {t('useResponsesApi')}
{responseApiSupported === false && (

- Response API is not supported by this model + {t('responseApiUnsupported')}

)} {isCheckingResponseApi && (

- Checking Response API support... + {t('checkingResponseApi')}

)}
@@ -443,6 +444,7 @@ export function VLMSettings({ interface ModelAvailabilityCheckProps { modelConfig: { baseUrl: string; + // secretlint-disable-next-line @secretlint/secretlint-rule-pattern apiKey: string; modelName: string; }; @@ -465,6 +467,7 @@ export function ModelAvailabilityCheck({ className, onResponseApiSupportChange, }: ModelAvailabilityCheckProps) { + const { t } = useI18n(); const [checkState, setCheckState] = useState({ status: 'idle' }); const { baseUrl, apiKey, modelName } = modelConfig; @@ -492,9 +495,7 @@ export function ModelAvailabilityCheck({ e.stopPropagation(); if (!isConfigValid) { - toast.error( - 'Please fill in all required fields before checking model availability', - ); + toast.error(t('fillRequiredBeforeModelCheck')); return; } @@ -509,11 +510,12 @@ export function ModelAvailabilityCheck({ onResponseApiSupportChange?.(responseApiSupported); if (isAvailable) { - const successMessage = `Model "${modelName}" is available and working correctly${ - responseApiSupported - ? '. Response API is supported.' - : '. But Response API is not supported.' - }`; + const successMessage = t('modelAvailable', { + modelName, + suffix: responseApiSupported + ? t('responseApiSupported') + : t('responseApiNotSupported'), + }); setCheckState({ status: 'success', message: successMessage, @@ -523,7 +525,7 @@ export function ModelAvailabilityCheck({ responseApiSupported, }); } else { - const errorMessage = `Model "${modelName}" is not responding correctly`; + const errorMessage = t('modelNotResponding', { modelName }); setCheckState({ status: 'error', message: errorMessage, @@ -533,8 +535,10 @@ export function ModelAvailabilityCheck({ } } catch (error) { const errorMessage = - error instanceof Error ? error.message : 'Unknown error occurred'; - const fullErrorMessage = `Failed to connect to model: ${errorMessage}`; + error instanceof Error ? error.message : t('unknownError'); + const fullErrorMessage = t('failedConnectModel', { + message: errorMessage, + }); setCheckState({ status: 'error', @@ -564,10 +568,10 @@ export function ModelAvailabilityCheck({ {checkState.status === 'checking' ? ( <> - Checking Model... + {t('checkingModel')} ) : ( - 'Check Model Availability' + t('checkModelAvailability') )} diff --git a/apps/ui-tars/src/renderer/src/components/Settings/global.tsx b/apps/ui-tars/src/renderer/src/components/Settings/global.tsx index 0807929572..1d8929ed1c 100644 --- a/apps/ui-tars/src/renderer/src/components/Settings/global.tsx +++ b/apps/ui-tars/src/renderer/src/components/Settings/global.tsx @@ -27,6 +27,7 @@ import { ChatSettings } from './category/chat'; import { LocalBrowserSettings } from './category/localBrowser'; import { ReportSettings } from './category/report'; import { GeneralSettings } from './category/general'; +import { useI18n } from '../../i18n'; interface GlobalSettingsStore { isOpen: boolean; @@ -43,13 +44,14 @@ export const useGlobalSettings = create((set) => ({ })); export const GlobalSettings = () => { + const { t } = useI18n(); const { isOpen, toggleSettings } = useGlobalSettings(); return ( - Settings + {t('settings')} @@ -60,35 +62,35 @@ export const GlobalSettings = () => { className="w-full justify-start gap-2 px-2 py-1.5 mb-2 !shadow-none font-normal data-[state=active]:font-medium data-[state=active]:bg-accent data-[state=active]:text-accent-foreground hover:bg-accent/50" > - VLM Settings + {t('vlmSettings')} - Chat Settings + {t('chatSettings')} - Operator Settings + {t('operatorSettings')} - Report Settings + {t('reportSettings')} - General Settings + {t('generalSettings')}
@@ -96,14 +98,18 @@ export const GlobalSettings = () => {
-

VLM Settings

+

+ {t('vlmSettings')} +

-

Chat Settings

+

+ {t('chatSettings')} +

@@ -111,22 +117,26 @@ export const GlobalSettings = () => {

- Local Operator Settings + {t('localOperatorSettings')}

- Local Browser Operator + {t('localBrowserOperator')}

-

Report Settings

+

+ {t('reportSettings')} +

-

General Settings

+

+ {t('generalSettings')} +

diff --git a/apps/ui-tars/src/renderer/src/components/Settings/local.tsx b/apps/ui-tars/src/renderer/src/components/Settings/local.tsx index 8378eaa93b..7caa4c1f6d 100644 --- a/apps/ui-tars/src/renderer/src/components/Settings/local.tsx +++ b/apps/ui-tars/src/renderer/src/components/Settings/local.tsx @@ -10,6 +10,7 @@ import { LocalStore } from '@main/store/validate'; import { VLMSettings, VLMSettingsRef } from './category/vlm'; import { useRef } from 'react'; +import { useI18n } from '../../i18n'; interface LocalSettingsDialogProps { isOpen: boolean; @@ -36,6 +37,7 @@ export const LocalSettingsDialog = ({ onSubmit, onClose, }: LocalSettingsDialogProps) => { + const { t } = useI18n(); const vlmSettingsRef = useRef(null); const handleGetStart = async () => { @@ -51,15 +53,12 @@ export const LocalSettingsDialog = ({ !open && onClose()}> - VLM Settings - - Enter VLM settings to enable the model to control the local computer - or browser. - + {t('vlmSettings')} + {t('vlmDialogDescription')} diff --git a/apps/ui-tars/src/renderer/src/components/SideBar/app-sidebar.tsx b/apps/ui-tars/src/renderer/src/components/SideBar/app-sidebar.tsx index 9919061453..3094127cca 100644 --- a/apps/ui-tars/src/renderer/src/components/SideBar/app-sidebar.tsx +++ b/apps/ui-tars/src/renderer/src/components/SideBar/app-sidebar.tsx @@ -27,8 +27,10 @@ import { useStore } from '../../hooks/useStore'; import { StatusEnum } from '@ui-tars/sdk'; import { NavDialog } from '../AlertDialog/navDialog'; import { api } from '../../api'; +import { useI18n } from '../../i18n'; export function AppSidebar({ ...props }: ComponentProps) { + const { t } = useI18n(); const { currentSessionId, sessions, @@ -150,7 +152,7 @@ export function AppSidebar({ ...props }: ComponentProps) { onClick={handleHomeClick} > - Home + {t('home')} diff --git a/apps/ui-tars/src/renderer/src/components/SideBar/nav-footer.tsx b/apps/ui-tars/src/renderer/src/components/SideBar/nav-footer.tsx index 0cceb4e6f4..c484668799 100644 --- a/apps/ui-tars/src/renderer/src/components/SideBar/nav-footer.tsx +++ b/apps/ui-tars/src/renderer/src/components/SideBar/nav-footer.tsx @@ -9,18 +9,21 @@ import { SidebarMenu, SidebarMenuButton, } from '@renderer/components/ui/sidebar'; +import { useI18n } from '../../i18n'; interface NavSettingsProps { onClick: () => void; } export function NavSettings({ onClick }: NavSettingsProps) { + const { t } = useI18n(); + return ( - Settings + {t('settings')} diff --git a/apps/ui-tars/src/renderer/src/components/SideBar/nav-history.tsx b/apps/ui-tars/src/renderer/src/components/SideBar/nav-history.tsx index 373cad53a0..3afbb16a17 100644 --- a/apps/ui-tars/src/renderer/src/components/SideBar/nav-history.tsx +++ b/apps/ui-tars/src/renderer/src/components/SideBar/nav-history.tsx @@ -39,6 +39,7 @@ import { ShareOptions } from './share'; import { Operator } from '@main/store/types'; import { DeleteSessionDialog } from '@renderer/components/AlertDialog/delSessionDialog'; +import { useI18n } from '../../i18n'; const getIcon = (operator: Operator, isActive: boolean) => { const isRemote = @@ -71,6 +72,7 @@ export function NavHistory({ onSessionClick: (id: string) => void; onSessionDelete: (id: string) => void; }) { + const { t } = useI18n(); const [isShareConfirmOpen, setIsShareConfirmOpen] = useState(false); const [id, setId] = useState(''); const [isHistoryOpen, setIsHistoryOpen] = useState(true); @@ -108,7 +110,7 @@ export function NavHistory({ onClick={handleHistory} > - History + {t('history')} @@ -130,7 +132,7 @@ export function NavHistory({ - More + {t('more')} handleDelete(item.id)} > - Delete + {t('delete')} diff --git a/apps/ui-tars/src/renderer/src/components/SideBar/nav-main.tsx b/apps/ui-tars/src/renderer/src/components/SideBar/nav-main.tsx index e9037c0649..a84528ebc0 100644 --- a/apps/ui-tars/src/renderer/src/components/SideBar/nav-main.tsx +++ b/apps/ui-tars/src/renderer/src/components/SideBar/nav-main.tsx @@ -19,6 +19,7 @@ import { SidebarMenuSubButton, SidebarMenuSubItem, } from '@renderer/components/ui/sidebar'; +import { useI18n } from '../../i18n'; export function NavMain({ items, @@ -34,9 +35,11 @@ export function NavMain({ }[]; }[]; }) { + const { t } = useI18n(); + return ( - Platform + {t('platform')} {items.map((item) => ( (() => { + const browserLanguage = navigator.language.toLowerCase(); + if (settings.language === 'zh' || browserLanguage.startsWith('zh')) { + return 'zh'; + } + + return 'en'; + }, [settings.language]); + + const t = useCallback( + (key: TranslationKey, values?: Record) => { + let message: string = translations[language][key] || translations.en[key]; + + if (values) { + Object.entries(values).forEach(([name, value]) => { + message = message.replace(`{${name}}`, String(value)); + }); + } + + return message; + }, + [language], + ); + + return { language, t }; +} diff --git a/apps/ui-tars/src/renderer/src/pages/home/index.tsx b/apps/ui-tars/src/renderer/src/pages/home/index.tsx index 9a234f87c5..c1408ffbf1 100644 --- a/apps/ui-tars/src/renderer/src/pages/home/index.tsx +++ b/apps/ui-tars/src/renderer/src/pages/home/index.tsx @@ -31,8 +31,10 @@ import { sleep } from '@ui-tars/shared/utils'; import { FreeTrialDialog } from '../../components/AlertDialog/freeTrialDialog'; import { DragArea } from '../../components/Common/drag'; import { OPERATOR_URL_MAP } from '../../const'; +import { useI18n } from '../../i18n'; const Home = () => { + const { t } = useI18n(); const navigate = useNavigate(); const { createSession } = useSession(); const [localConfig, setLocalConfig] = useState({ @@ -46,7 +48,7 @@ const Home = () => { const toRemoteComputer = async (value: 'free' | 'paid') => { console.log('toRemoteComputer', value); - const session = await createSession('New Session', { + const session = await createSession(t('newSession'), { operator: Operator.RemoteComputer, isFree: value === 'free', }); @@ -77,7 +79,7 @@ const Home = () => { const toRemoteBrowser = async (value: 'free' | 'paid') => { console.log('toRemoteBrowser', value); - const session = await createSession('New Session', { + const session = await createSession(t('newSession'), { operator: Operator.RemoteBrowser, isFree: value === 'free', }); @@ -106,7 +108,7 @@ const Home = () => { /** local click logic start */ const toLocal = async (operator: Operator) => { - const session = await createSession('New Session', { + const session = await createSession(t('newSession'), { operator: operator, }); @@ -158,16 +160,13 @@ const Home = () => {
-

- Welcome to UI-TARS Desktop -

+

{t('appTitle')}

- You can also experience the remote versions on Volcano - Engine:  + {t('remoteVolcanoIntro')} 

-  and  +  / 
@@ -200,10 +199,9 @@ const Home = () => {
- Computer Operator + {t('computerOperator')} - Use the UI-TARS model to automate and complete tasks directly on - your computer with AI assistance. + {t('computerOperatorDescription')} @@ -218,16 +216,15 @@ const Home = () => { onClick={() => handleLocalPress(Operator.LocalComputer)} className="w-full" > - Use Local Computer + {t('useLocalComputer')} - Browser Operator + {t('browserOperator')} - Let the UI-TARS model help you automate browser tasks, from - navigating pages to filling out forms. + {t('browserOperatorDescription')} @@ -242,7 +239,7 @@ const Home = () => { onClick={() => handleLocalPress(Operator.LocalBrowser)} className="w-full" > - Use Local Browser + {t('useLocalBrowser')} diff --git a/apps/ui-tars/src/renderer/src/pages/local/index.tsx b/apps/ui-tars/src/renderer/src/pages/local/index.tsx index 5a83a6b8b1..93514fd5c7 100644 --- a/apps/ui-tars/src/renderer/src/pages/local/index.tsx +++ b/apps/ui-tars/src/renderer/src/pages/local/index.tsx @@ -37,6 +37,8 @@ import { LocalSettingsDialog, } from '../../components/Settings/local'; import { sleep } from '@ui-tars/shared/utils'; +import { useI18n } from '../../i18n'; +import { Operator } from '@main/store/types'; const getFinishedContent = (predictionParsed?: PredictionParsed[]) => predictionParsed?.find( @@ -46,7 +48,15 @@ const getFinishedContent = (predictionParsed?: PredictionParsed[]) => step.action_inputs.content.trim() !== '', )?.action_inputs?.content as string | undefined; +const operatorTitleKeyMap = { + [Operator.LocalComputer]: 'localComputerOperator', + [Operator.LocalBrowser]: 'localBrowserOperator', + [Operator.RemoteComputer]: 'remoteComputerOperator', + [Operator.RemoteBrowser]: 'remoteBrowserOperator', +} as const; + const LocalOperator = () => { + const { t } = useI18n(); const state = useLocation().state as RouterState; const navigate = useNavigate(); const { setOpen } = useSidebar(); @@ -138,7 +148,7 @@ const LocalOperator = () => { status === StatusEnum.PAUSE; const onNewChat = useCallback(async () => { - const session = await createSession('New Session', { + const session = await createSession(t('newSession'), { operator: state.operator, }); @@ -261,7 +271,7 @@ const LocalOperator = () => { ); })} - {thinking && } + {thinking && } {errorMsg && }
@@ -271,7 +281,7 @@ const LocalOperator = () => { return (
@@ -284,7 +294,7 @@ const LocalOperator = () => { >
{renderChatList()} @@ -298,7 +308,7 @@ const LocalOperator = () => { - ScreenShot + {t('screenshot')}