diff --git a/web/src/app.tsx b/web/src/app.tsx
index 746b64995555e0401c5d62b4fb8e0e952fd3dd57..e33201a9408dd94b22bd6d68cb433ef5bfa7d583 100644
--- a/web/src/app.tsx
+++ b/web/src/app.tsx
@@ -1,7 +1,26 @@
-import { App, ConfigProvider } from 'antd';
-import { ReactNode } from 'react';
+import i18next from '@/locales/config';
+import { App, ConfigProvider, ConfigProviderProps } from 'antd';
+import enUS from 'antd/locale/en_US';
+import zhCN from 'antd/locale/zh_CN';
+import React, { ReactNode, useEffect, useState } from 'react';
+import storage from './utils/authorizationUtil';
+
+type Locale = ConfigProviderProps['locale'];
+
+const RootProvider = ({ children }: React.PropsWithChildren) => {
+  const getLocale = (lng: string) => (lng === 'zh' ? zhCN : enUS);
+
+  const [locale, setLocal] = useState<Locale>(getLocale(storage.getLanguage()));
+
+  i18next.on('languageChanged', function (lng: string) {
+    storage.setLanguage(lng);
+    setLocal(getLocale(lng));
+  });
+
+  useEffect(() => {
+    i18next.changeLanguage(storage.getLanguage());
+  }, [locale]);
 
-export function rootContainer(container: ReactNode) {
   return (
     <ConfigProvider
       theme={{
@@ -9,8 +28,13 @@ export function rootContainer(container: ReactNode) {
           fontFamily: 'Inter',
         },
       }}
+      locale={locale}
     >
-      <App> {container}</App>
+      <App> {children}</App>
     </ConfigProvider>
   );
+};
+
+export function rootContainer(container: ReactNode) {
+  return <RootProvider>{container}</RootProvider>;
 }
diff --git a/web/src/components/chunk-method-modal/index.tsx b/web/src/components/chunk-method-modal/index.tsx
index f4ecbd958d5b2b75fec3ee4f293dfd13e72bda96..7f592b5462e5ad14cefa196a9bcb99d7b96eab0b 100644
--- a/web/src/components/chunk-method-modal/index.tsx
+++ b/web/src/components/chunk-method-modal/index.tsx
@@ -134,12 +134,8 @@ const ChunkMethodModal: React.FC<IProps> = ({
         {showPages && (
           <>
             <Space>
-              <p>Page Ranges:</p>
-              <Tooltip
-                title={
-                  'page ranges: Define the page ranges that need to be parsed. The pages that not included in these ranges will be ignored.'
-                }
-              >
+              <p>{t('pageRanges')}:</p>
+              <Tooltip title={t('pageRangesTip')}>
                 <QuestionCircleOutlined
                   className={styles.questionIcon}
                 ></QuestionCircleOutlined>
@@ -163,7 +159,7 @@ const ChunkMethodModal: React.FC<IProps> = ({
                         rules={[
                           {
                             required: true,
-                            message: 'Missing start page number',
+                            message: t('fromMessage'),
                           },
                           ({ getFieldValue }) => ({
                             validator(_, value) {
@@ -175,16 +171,14 @@ const ChunkMethodModal: React.FC<IProps> = ({
                                 return Promise.resolve();
                               }
                               return Promise.reject(
-                                new Error(
-                                  'The current value must be greater than the previous to!',
-                                ),
+                                new Error(t('greaterThanPrevious')),
                               );
                             },
                           }),
                         ]}
                       >
                         <InputNumber
-                          placeholder="from"
+                          placeholder={t('fromPlaceholder')}
                           min={0}
                           precision={0}
                           className={styles.pageInputNumber}
@@ -197,7 +191,7 @@ const ChunkMethodModal: React.FC<IProps> = ({
                         rules={[
                           {
                             required: true,
-                            message: 'Missing end page number(excluded)',
+                            message: t('toMessage'),
                           },
                           ({ getFieldValue }) => ({
                             validator(_, value) {
@@ -208,16 +202,14 @@ const ChunkMethodModal: React.FC<IProps> = ({
                                 return Promise.resolve();
                               }
                               return Promise.reject(
-                                new Error(
-                                  'The current value must be greater than to!',
-                                ),
+                                new Error(t('greaterThan')),
                               );
                             },
                           }),
                         ]}
                       >
                         <InputNumber
-                          placeholder="to"
+                          placeholder={t('toPlaceholder')}
                           min={0}
                           precision={0}
                           className={styles.pageInputNumber}
@@ -235,7 +227,7 @@ const ChunkMethodModal: React.FC<IProps> = ({
                       block
                       icon={<PlusOutlined />}
                     >
-                      Add page
+                      {t('addPage')}
                     </Button>
                   </Form.Item>
                 </>
@@ -246,12 +238,10 @@ const ChunkMethodModal: React.FC<IProps> = ({
         {showOne && (
           <Form.Item
             name={['parser_config', 'layout_recognize']}
-            label="Layout recognize"
+            label={t('layoutRecognize')}
             initialValue={true}
             valuePropName="checked"
-            tooltip={
-              'Use visual models for layout analysis to better identify document structure, find where the titles, text blocks, images, and tables are. Without this feature, only the plain text of the PDF can be obtained.'
-            }
+            tooltip={t('layoutRecognizeTip')}
           >
             <Switch />
           </Form.Item>
@@ -265,14 +255,13 @@ const ChunkMethodModal: React.FC<IProps> = ({
               getFieldValue(['parser_config', 'layout_recognize']) && (
                 <Form.Item
                   name={['parser_config', 'task_page_size']}
-                  label="Task page size"
-                  tooltip={`If using layout recognize, the PDF file will be split into groups of successive. Layout analysis will be performed parallelly between groups to increase the processing speed. 
-                    The 'Task page size' determines the size of groups. The larger the page size is, the lower the chance of splitting continuous text between pages into different chunks.`}
+                  label={t('taskPageSize')}
+                  tooltip={t('taskPageSizeTip')}
                   initialValue={12}
                   rules={[
                     {
                       required: true,
-                      message: 'Please input your task page size!',
+                      message: t('taskPageSizeMessage'),
                     },
                   ]}
                 >
diff --git a/web/src/components/max-token-number.tsx b/web/src/components/max-token-number.tsx
index 43618be4fcfa8d6aa5bb6182aaaf3609890e3fcf..9913b035bc0c02af02b9c495c02df45b82041d25 100644
--- a/web/src/components/max-token-number.tsx
+++ b/web/src/components/max-token-number.tsx
@@ -1,18 +1,18 @@
+import { useTranslate } from '@/hooks/commonHooks';
 import { Flex, Form, InputNumber, Slider } from 'antd';
 
 const MaxTokenNumber = () => {
+  const { t } = useTranslate('knowledgeConfiguration');
+
   return (
-    <Form.Item
-      label="Chunk token number"
-      tooltip="It determine the token number of a chunk approximately."
-    >
+    <Form.Item label={t('chunkTokenNumber')} tooltip={t('chunkTokenNumberTip')}>
       <Flex gap={20} align="center">
         <Flex flex={1}>
           <Form.Item
             name={['parser_config', 'chunk_token_num']}
             noStyle
             initialValue={128}
-            rules={[{ required: true, message: 'Province is required' }]}
+            rules={[{ required: true, message: t('chunkTokenNumberMessage') }]}
           >
             <Slider max={2048} style={{ width: '100%' }} />
           </Form.Item>
@@ -20,7 +20,7 @@ const MaxTokenNumber = () => {
         <Form.Item
           name={['parser_config', 'chunk_token_num']}
           noStyle
-          rules={[{ required: true, message: 'Street is required' }]}
+          rules={[{ required: true, message: t('chunkTokenNumberMessage') }]}
         >
           <InputNumber max={2048} min={0} />
         </Form.Item>
diff --git a/web/src/components/rename-modal/index.tsx b/web/src/components/rename-modal/index.tsx
index 9802ff88f9cba5372c779dd2162de3fe33c3be36..afe5b7f67dee8da5c00b82cbccc6bba66818cfc0 100644
--- a/web/src/components/rename-modal/index.tsx
+++ b/web/src/components/rename-modal/index.tsx
@@ -1,3 +1,4 @@
+import { useTranslate } from '@/hooks/commonHooks';
 import { Form, Input, Modal } from 'antd';
 import { useEffect } from 'react';
 import { IModalManagerChildrenProps } from '../modal-manager';
@@ -17,6 +18,7 @@ const RenameModal = ({
   onOk,
 }: IProps) => {
   const [form] = Form.useForm();
+  const { t } = useTranslate('common');
 
   type FieldType = {
     name?: string;
@@ -48,7 +50,7 @@ const RenameModal = ({
 
   return (
     <Modal
-      title="Rename"
+      title={t('rename')}
       open={visible}
       onOk={handleOk}
       onCancel={handleCancel}
@@ -66,9 +68,9 @@ const RenameModal = ({
         form={form}
       >
         <Form.Item<FieldType>
-          label="Name"
+          label={t('name')}
           name="name"
-          rules={[{ required: true, message: 'Please input name!' }]}
+          rules={[{ required: true, message: t('namePlaceholder') }]}
         >
           <Input />
         </Form.Item>
diff --git a/web/src/global.ts b/web/src/global.ts
deleted file mode 100644
index d025e4a3373ad39de74782143886e41efab0405d..0000000000000000000000000000000000000000
--- a/web/src/global.ts
+++ /dev/null
@@ -1 +0,0 @@
-import '@/locales/config';
diff --git a/web/src/hooks/commonHooks.tsx b/web/src/hooks/commonHooks.tsx
index 4125cd7cdb8e0691ca86fed0e8e647844727002f..03a16509b24ed89f1bbf8671fa9d19026ce0a70f 100644
--- a/web/src/hooks/commonHooks.tsx
+++ b/web/src/hooks/commonHooks.tsx
@@ -119,3 +119,7 @@ export const useShowDeleteConfirm = () => {
 export const useTranslate = (keyPrefix: string) => {
   return useTranslation('translation', { keyPrefix });
 };
+
+export const useCommonTranslation = () => {
+  return useTranslation('translation', { keyPrefix: 'common' });
+};
diff --git a/web/src/hooks/logicHooks.ts b/web/src/hooks/logicHooks.ts
index 42dea0ffd2b19ab42123259012cabf23d92149b5..23833db99845b67709d704c27bff3fbe720e64ff 100644
--- a/web/src/hooks/logicHooks.ts
+++ b/web/src/hooks/logicHooks.ts
@@ -1,9 +1,11 @@
 import { IKnowledgeFile } from '@/interfaces/database/knowledge';
 import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
 import { useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
 import { useSetModalState } from './commonHooks';
 import { useSetDocumentParser } from './documentHooks';
 import { useOneNamespaceEffectsLoading } from './storeHooks';
+import { useSaveSetting } from './userSettingHook';
 
 export const useChangeDocumentParser = (documentId: string) => {
   const setDocumentParser = useSetDocumentParser();
@@ -45,3 +47,15 @@ export const useSetSelectedRecord = <T = IKnowledgeFile>() => {
 
   return { currentRecord, setRecord };
 };
+
+export const useChangeLanguage = () => {
+  const { i18n } = useTranslation();
+  const saveSetting = useSaveSetting();
+
+  const changeLanguage = (lng: string) => {
+    i18n.changeLanguage(lng === 'Chinese' ? 'zh' : 'en');
+    saveSetting({ language: lng });
+  };
+
+  return changeLanguage;
+};
diff --git a/web/src/hooks/userSettingHook.ts b/web/src/hooks/userSettingHook.ts
index c6d5065a7592b3c37bf7b0a23be8b65fa2890346..79f138121d03f8943af22de0517a4f77190911f3 100644
--- a/web/src/hooks/userSettingHook.ts
+++ b/web/src/hooks/userSettingHook.ts
@@ -84,7 +84,7 @@ export const useSaveSetting = () => {
   const dispatch = useDispatch();
 
   const saveSetting = useCallback(
-    (userInfo: { new_password: string } | IUserInfo): number => {
+    (userInfo: { new_password: string } | Partial<IUserInfo>): number => {
       return dispatch<any>({ type: 'settingModel/setting', payload: userInfo });
     },
     [dispatch],
diff --git a/web/src/layouts/components/right-toolbar/index.tsx b/web/src/layouts/components/right-toolbar/index.tsx
index e5df898f43f6a1c53967a5aa5f5d853e9239d653..faca5c903f3e2db628513af8ee8b6cb661eab9c7 100644
--- a/web/src/layouts/components/right-toolbar/index.tsx
+++ b/web/src/layouts/components/right-toolbar/index.tsx
@@ -1,11 +1,19 @@
+import { ReactComponent as TranslationIcon } from '@/assets/svg/translation.svg';
+import { useTranslate } from '@/hooks/commonHooks';
 import { GithubOutlined } from '@ant-design/icons';
-import { Space } from 'antd';
+import { Dropdown, MenuProps, Space } from 'antd';
 import React from 'react';
 import User from '../user';
+
+import { useChangeLanguage } from '@/hooks/logicHooks';
 import styled from './index.less';
 
-const Circle = ({ children }: React.PropsWithChildren) => {
-  return <div className={styled.circle}>{children}</div>;
+const Circle = ({ children, ...restProps }: React.PropsWithChildren) => {
+  return (
+    <div {...restProps} className={styled.circle}>
+      {children}
+    </div>
+  );
 };
 
 const handleGithubCLick = () => {
@@ -13,17 +21,38 @@ const handleGithubCLick = () => {
 };
 
 const RightToolBar = () => {
+  const { t } = useTranslate('common');
+  const changeLanguage = useChangeLanguage();
+
+  const handleItemClick: MenuProps['onClick'] = ({ key }) => {
+    changeLanguage(key);
+  };
+
+  const items: MenuProps['items'] = [
+    {
+      key: 'English',
+      label: <span>{t('english')}</span>,
+    },
+    { type: 'divider' },
+    {
+      key: 'Chinese',
+      label: <span>{t('chinese')}</span>,
+    },
+  ];
+
   return (
     <div className={styled.toolbarWrapper}>
       <Space wrap size={16}>
         <Circle>
           <GithubOutlined onClick={handleGithubCLick} />
         </Circle>
+        <Dropdown menu={{ items, onClick: handleItemClick }} placement="bottom">
+          <Circle>
+            <TranslationIcon />
+          </Circle>
+        </Dropdown>
         {/* <Circle>
-          <TranslationIcon />
-        </Circle>
-        <Circle>
-          <MoonIcon />
+          <MonIcon />
         </Circle> */}
         <User></User>
       </Space>
diff --git a/web/src/locales/config.ts b/web/src/locales/config.ts
index 311f5d200f049bd144e5cceed229acd0da3f2777..17b7a7f2b20cdbcbf113f44e26d393fea28b8010 100644
--- a/web/src/locales/config.ts
+++ b/web/src/locales/config.ts
@@ -1,8 +1,8 @@
 import i18n from 'i18next';
 import { initReactI18next } from 'react-i18next';
 
-import translation_en from './en.json';
-import translation_zh from './zh.json';
+import translation_en from './en';
+import translation_zh from './zh';
 
 const resources = {
   en: translation_en,
diff --git a/web/src/locales/en.json b/web/src/locales/en.json
deleted file mode 100644
index 027d7b7ec53137f064fce4bb952840aec8ae88cb..0000000000000000000000000000000000000000
--- a/web/src/locales/en.json
+++ /dev/null
@@ -1,122 +0,0 @@
-{
-  "translation": {
-    "common": {
-      "delete": "Delete",
-      "deleteModalTitle": "Are you sure delete this item?",
-      "ok": "Yes",
-      "cancel": "No",
-      "total": "Total",
-      "rename": "Rename",
-      "name": "Name",
-      "namePlaceholder": "Please input name"
-    },
-    "login": {
-      "login": "Sign in",
-      "signUp": "Sign up",
-      "loginDescription": "We’re so excited to see you again!",
-      "registerDescription": "Glad to have you on board!",
-      "emailLabel": "Email",
-      "emailPlaceholder": "Please input email",
-      "passwordLabel": "Password",
-      "passwordPlaceholder": "Please input password",
-      "rememberMe": "Remember me",
-      "signInTip": "Don’t have an account?",
-      "signUpTip": "Already have an account?",
-      "nicknameLabel": "Nickname",
-      "nicknamePlaceholder": "Please input nickname",
-      "register": "Create an account",
-      "continue": "Continue"
-    },
-    "header": {
-      "knowledgeBase": "Knowledge Base",
-      "chat": "Chat",
-      "register": "Register",
-      "signin": "Sign in",
-      "home": "Home",
-      "setting": "用户设置",
-      "logout": "登出"
-    },
-    "knowledgeList": {
-      "welcome": "Welcome back",
-      "description": "Which database are we going to use today?",
-      "createKnowledgeBase": "Create knowledge base",
-      "name": "Name",
-      "namePlaceholder": "Please input name!",
-      "doc": "Docs"
-    },
-    "knowledgeDetails": {
-      "dataset": "Dataset",
-      "testing": "Retrieval testing",
-      "configuration": "Configuration",
-      "name": "Name",
-      "namePlaceholder": "Please input name!",
-      "doc": "Docs",
-      "datasetDescription": "Hey, don't forget to adjust the chunk after adding the dataset! 😉",
-      "addFile": "Add file",
-      "searchFiles": "Search your files",
-      "localFiles": "Local files",
-      "emptyFiles": "Create empty file",
-      "chunkNumber": "Chunk Number",
-      "uploadDate": "Upload Date",
-      "chunkMethod": "Chunk Method",
-      "enabled": "Enabled",
-      "action": "Action",
-      "parsingStatus": "Parsing Status",
-      "processBeginAt": "Process Begin At",
-      "processDuration": "Process Duration",
-      "progressMsg": "Progress Msg",
-      "testingDescription": "Final step! After success, leave the rest to Infiniflow AI.",
-      "topK": "Top K",
-      "topKTip": "For the computaion cost, not all the retrieved chunk will be computed vector cosine similarity with query. The bigger the 'Top K' is, the higher the recall rate is, the slower the retrieval speed is.",
-      "similarityThreshold": "Similarity threshold",
-      "similarityThresholdTip": "We use hybrid similarity score to evaluate distance between two lines of text. It's weighted keywords similarity and vector cosine similarity. If the similarity between query and chunk is less than this threshold, the chunk will be filtered out.",
-      "vectorSimilarityWeight": "Vector similarity weight",
-      "vectorSimilarityWeightTip": "We use hybrid similarity score to evaluate distance between two lines of text. It's weighted keywords similarity and vector cosine similarity. The sum of both weights is 1.0.",
-      "testText": "Test text",
-      "testTextPlaceholder": "Please input your question!",
-      "testingLabel": "Testing",
-      "similarity": "Hybrid Similarity",
-      "termSimilarity": "Term Similarity",
-      "vectorSimilarity": "Vector Similarity",
-      "hits": "Hits",
-      "view": "View",
-      "filesSelected": "Files Selected"
-    },
-    "knowledgeConfiguration": {
-      "titleDescription": "Update your knowledge base details especially parsing method here.",
-      "name": "Knowledge base name",
-      "photo": "Knowledge base photo",
-      "description": "Description",
-      "language": "Language",
-      "languageMessage": "Please input your language!",
-      "languagePlaceholder": "Please input your language!",
-      "permissions": "Permissions",
-      "embeddingModel": "Embedding model",
-      "chunkTokenNumber": "Chunk token number",
-      "embeddingModelTip": "The embedding model used to embedding chunks. It's unchangable once the knowledgebase has chunks. You need to delete all the chunks if you want to change it.",
-      "permissionsTip": "If the permission is 'Team', all the team member can manipulate the knowledgebase.",
-      "chunkTokenNumberTip": "It determine the token number of a chunk approximately.",
-      "chunkMethodTip": "The instruction is at right.",
-      "upload": "Upload",
-      "english": "English",
-      "chinese": "Chinese",
-      "embeddingModelPlaceholder": "Please select a embedding model",
-      "chunkMethodPlaceholder": "Please select a chunk method",
-      "save": "Save",
-      "me": "Only me",
-      "team": "Team",
-      "cancel": "Cancel"
-    },
-    "footer": {
-      "detail": "All rights reserved @ React"
-    },
-    "layout": {
-      "file": "file",
-      "knowledge": "knowledge",
-      "chat": "chat"
-    },
-    "setting": {
-      "btn": "en"
-    }
-  }
-}
diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts
new file mode 100644
index 0000000000000000000000000000000000000000..487b5c313b06ff1744c8d9e6424421c7c66c0632
--- /dev/null
+++ b/web/src/locales/en.ts
@@ -0,0 +1,433 @@
+export default {
+  translation: {
+    common: {
+      delete: 'Delete',
+      deleteModalTitle: 'Are you sure delete this item?',
+      ok: 'Yes',
+      cancel: 'No',
+      total: 'Total',
+      rename: 'Rename',
+      name: 'Name',
+      save: 'Save',
+      namePlaceholder: 'Please input name',
+      next: 'Next',
+      create: 'Create',
+      edit: 'Edit',
+      upload: 'Upload',
+      english: 'English',
+      chinese: 'Chinese',
+      language: 'Language',
+      languageMessage: 'Please input your language!',
+      languagePlaceholder: 'select your language',
+    },
+    login: {
+      login: 'Sign in',
+      signUp: 'Sign up',
+      loginDescription: 'We’re so excited to see you again!',
+      registerDescription: 'Glad to have you on board!',
+      emailLabel: 'Email',
+      emailPlaceholder: 'Please input email',
+      passwordLabel: 'Password',
+      passwordPlaceholder: 'Please input password',
+      rememberMe: 'Remember me',
+      signInTip: 'Don’t have an account?',
+      signUpTip: 'Already have an account?',
+      nicknameLabel: 'Nickname',
+      nicknamePlaceholder: 'Please input nickname',
+      register: 'Create an account',
+      continue: 'Continue',
+      title: 'Start building your smart assistants.',
+      description:
+        'Sign up for free to explore top RAG technology. Create knowledge bases and AIs to empower your business.',
+      review: 'from 500+ reviews',
+    },
+    header: {
+      knowledgeBase: 'Knowledge Base',
+      chat: 'Chat',
+      register: 'Register',
+      signin: 'Sign in',
+      home: 'Home',
+      setting: '用户设置',
+      logout: '登出',
+    },
+    knowledgeList: {
+      welcome: 'Welcome back',
+      description: 'Which knowledge base are we going to use today?',
+      createKnowledgeBase: 'Create knowledge base',
+      name: 'Name',
+      namePlaceholder: 'Please input name!',
+      doc: 'Docs',
+    },
+    knowledgeDetails: {
+      dataset: 'Dataset',
+      testing: 'Retrieval testing',
+      files: 'files',
+      configuration: 'Configuration',
+      name: 'Name',
+      namePlaceholder: 'Please input name!',
+      doc: 'Docs',
+      datasetDescription:
+        "Hey, don't forget to adjust the chunk after adding the dataset! 😉",
+      addFile: 'Add file',
+      searchFiles: 'Search your files',
+      localFiles: 'Local files',
+      emptyFiles: 'Create empty file',
+      chunkNumber: 'Chunk Number',
+      uploadDate: 'Upload Date',
+      chunkMethod: 'Chunk Method',
+      enabled: 'Enabled',
+      action: 'Action',
+      parsingStatus: 'Parsing Status',
+      processBeginAt: 'Process Begin At',
+      processDuration: 'Process Duration',
+      progressMsg: 'Progress Msg',
+      testingDescription:
+        'Final step! After success, leave the rest to Infiniflow AI.',
+      topK: 'Top K',
+      topKTip:
+        "For the computaion cost, not all the retrieved chunk will be computed vector cosine similarity with query. The bigger the 'Top K' is, the higher the recall rate is, the slower the retrieval speed is.",
+      similarityThreshold: 'Similarity threshold',
+      similarityThresholdTip:
+        "We use hybrid similarity score to evaluate distance between two lines of text. It's weighted keywords similarity and vector cosine similarity. If the similarity between query and chunk is less than this threshold, the chunk will be filtered out.",
+      vectorSimilarityWeight: 'Vector similarity weight',
+      vectorSimilarityWeightTip:
+        "We use hybrid similarity score to evaluate distance between two lines of text. It's weighted keywords similarity and vector cosine similarity. The sum of both weights is 1.0.",
+      testText: 'Test text',
+      testTextPlaceholder: 'Please input your question!',
+      testingLabel: 'Testing',
+      similarity: 'Hybrid Similarity',
+      termSimilarity: 'Term Similarity',
+      vectorSimilarity: 'Vector Similarity',
+      hits: 'Hits',
+      view: 'View',
+      filesSelected: 'Files Selected',
+      upload: 'Upload',
+      runningStatus0: 'UNSTART',
+      runningStatus1: 'Parsing',
+      runningStatus2: 'CANCEL',
+      runningStatus3: 'SUCCESS',
+      runningStatus4: 'FAIL',
+      pageRanges: 'Page Ranges',
+      pageRangesTip:
+        'page ranges: Define the page ranges that need to be parsed. The pages that not included in these ranges will be ignored.',
+      fromPlaceholder: 'from',
+      fromMessage: 'Missing start page number',
+      toPlaceholder: 'to',
+      toMessage: 'Missing end page number(excluded)',
+      layoutRecognize: 'Layout recognize',
+      layoutRecognizeTip:
+        'Use visual models for layout analysis to better identify document structure, find where the titles, text blocks, images, and tables are. Without this feature, only the plain text of the PDF can be obtained.',
+      taskPageSize: 'Task page size',
+      taskPageSizeMessage: 'Please input your task page size!',
+      taskPageSizeTip: `If using layout recognize, the PDF file will be split into groups of successive. Layout analysis will be performed parallelly between groups to increase the processing speed. The 'Task page size' determines the size of groups. The larger the page size is, the lower the chance of splitting continuous text between pages into different chunks.`,
+      addPage: 'Add page',
+      greaterThan: 'The current value must be greater than to!',
+      greaterThanPrevious:
+        'The current value must be greater than the previous to!',
+      selectFiles: 'Select files',
+      changeSpecificCategory: 'Change specific category',
+      uploadTitle: 'Click or drag file to this area to upload',
+      uploadDescription:
+        'Support for a single or bulk upload. Strictly prohibited from uploading company data or other banned files.',
+    },
+    knowledgeConfiguration: {
+      titleDescription:
+        'Update your knowledge base details especially parsing method here.',
+      name: 'Knowledge base name',
+      photo: 'Knowledge base photo',
+      description: 'Description',
+      language: 'Language',
+      languageMessage: 'Please input your language!',
+      languagePlaceholder: 'Please input your language!',
+      permissions: 'Permissions',
+      embeddingModel: 'Embedding model',
+      chunkTokenNumber: 'Chunk token number',
+      chunkTokenNumberMessage: 'Chunk token number is required',
+      embeddingModelTip:
+        "The embedding model used to embedding chunks. It's unchangable once the knowledgebase has chunks. You need to delete all the chunks if you want to change it.",
+      permissionsTip:
+        "If the permission is 'Team', all the team member can manipulate the knowledgebase.",
+      chunkTokenNumberTip:
+        'It determine the token number of a chunk approximately.',
+      chunkMethod: 'Chunk method',
+      chunkMethodTip: 'The instruction is at right.',
+      upload: 'Upload',
+      english: 'English',
+      chinese: 'Chinese',
+      embeddingModelPlaceholder: 'Please select a embedding model',
+      chunkMethodPlaceholder: 'Please select a chunk method',
+      save: 'Save',
+      me: 'Only me',
+      team: 'Team',
+      cancel: 'Cancel',
+      methodTitle: 'Chunking Method Description',
+      methodExamples: 'Examples',
+      methodExamplesDescription:
+        'This visual guides is in order to make understanding easier for you.',
+      dialogueExamplesTitle: 'Dialogue Examples',
+      methodEmpty:
+        'This will display a visual explanation of the knowledge base categories',
+      book: `<p>Supported file formats are <b>DOCX</b>, <b>PDF</b>, <b>TXT</b>.</p><p>
+      Since a book is long and not all the parts are useful, if it's a PDF,
+      please setup the <i>page ranges</i> for every book in order eliminate negative effects and save computing time for analyzing.</p>`,
+      laws: `<p>Supported file formats are <b>DOCX</b>, <b>PDF</b>, <b>TXT</b>.</p><p>
+      Legal documents have a very rigorous writing format. We use text feature to detect split point. 
+      </p><p>
+      The chunk granularity is consistent with 'ARTICLE', and all the upper level text will be included in the chunk.
+      </p>`,
+      manual: `<p>Only <b>PDF</b> is supported.</p><p>
+      We assume manual has hierarchical section structure. We use the lowest section titles as pivots to slice documents.
+      So, the figures and tables in the same section will not be sliced apart, and chunk size might be large.
+      </p>`,
+      naive: `<p>Supported file formats are <b>DOCX, EXCEL, PPT, IMAGE, PDF, TXT</b>.</p>
+      <p>This method apply the naive ways to chunk files: </p>
+      <p>
+      <li>Successive text will be sliced into pieces using vision detection model.</li>
+      <li>Next, these successive pieces are merge into chunks whose token number is no more than 'Token number'.</li></p>`,
+      paper: `<p>Only <b>PDF</b> file is supported.</p><p>
+      If our model works well, the paper will be sliced by it's sections, like <i>abstract, 1.1, 1.2</i>, etc. </p><p>
+      The benefit of doing this is that LLM can better summarize the content of relevant sections in the paper, 
+      resulting in more comprehensive answers that help readers better understand the paper. 
+      The downside is that it increases the context of the LLM conversation and adds computational cost, 
+      so during the conversation, you can consider reducing the ‘<b>topN</b>’ setting.</p>`,
+      presentation: `<p>The supported file formats are <b>PDF</b>, <b>PPTX</b>.</p><p>
+      Every page will be treated as a chunk. And the thumbnail of every page will be stored.</p><p>
+      <i>All the PPT files you uploaded will be chunked by using this method automatically, setting-up for every PPT file is not necessary.</i></p>`,
+      qa: `<p><b>EXCEL</b> and <b>CSV/TXT</b> files are supported.</p><p>
+      If the file is in excel format, there should be 2 columns question and answer without header.
+      And question column is ahead of answer column.
+      And it's O.K if it has multiple sheets as long as the columns are rightly composed.</p><p>
+    
+      If it's in csv format, it should be UTF-8 encoded. Use TAB as delimiter to separate question and answer.</p><p>
+    
+      <i>All the deformed lines will be ignored.
+      Every pair of Q&A will be treated as a chunk.</i></p>`,
+      resume: `<p>The supported file formats are <b>DOCX</b>, <b>PDF</b>, <b>TXT</b>.
+      </p><p>
+      The résumé comes in a variety of formats, just like a person’s personality, but we often have to organize them into structured data that makes it easy to search.
+      </p><p>
+      Instead of chunking the résumé, we parse the résumé into structured data. As a HR, you can dump all the résumé you have, 
+      the you can list all the candidates that match the qualifications just by talk with <i>'RAGFlow'</i>.
+      </p>
+      `,
+      table: `<p><b>EXCEL</b> and <b>CSV/TXT</b> format files are supported.</p><p>
+      Here're some tips:
+      <ul>
+    <li>For csv or txt file, the delimiter between columns is <em><b>TAB</b></em>.</li>
+    <li>The first line must be column headers.</li>
+    <li>Column headers must be meaningful terms in order to make our LLM understanding.
+    It's good to enumerate some synonyms using slash <i>'/'</i> to separate, and even better to
+    enumerate values using brackets like <i>'gender/sex(male, female)'</i>.<p>
+    Here are some examples for headers:<ol>
+        <li>supplier/vendor<b>'TAB'</b>color(yellow, red, brown)<b>'TAB'</b>gender/sex(male, female)<b>'TAB'</b>size(M,L,XL,XXL)</li>
+        <li>姓名/名字<b>'TAB'</b>电话/手机/微信<b>'TAB'</b>最高学历(高中,职高,硕士,本科,博士,初中,中技,中专,专科,专升本,MPA,MBA,EMBA)</li>
+        </ol>
+        </p>
+    </li>
+    <li>Every row in table will be treated as a chunk.</li>
+    </ul>`,
+      picture: `
+    <p>Image files are supported. Video is coming soon.</p><p>
+    If the picture has text in it, OCR is applied to extract the text as its text description.
+    </p><p>
+    If the text extracted by OCR is not enough, visual LLM is used to get the descriptions.
+    </p>`,
+      one: `
+    <p>Supported file formats are <b>DOCX, EXCEL, PDF, TXT</b>.
+    </p><p>
+    For a document, it will be treated as an entire chunk, no split at all.
+    </p><p>
+    If you want to summarize something that needs all the context of an article and the selected LLM's context length covers the document length, you can try this method.
+    </p>`,
+    },
+    chunk: {
+      chunk: 'Chunk',
+      bulk: 'Bulk',
+      selectAll: 'Select All',
+      enabledSelected: 'Enable Selected',
+      disabledSelected: 'Disable Selected',
+      deleteSelected: 'Delete Selected',
+      search: 'Search',
+      all: 'All',
+      enabled: 'Enabled',
+      disabled: 'Disabled',
+      keyword: 'Keyword',
+      function: 'Function',
+      chunkMessage: 'Please input value!',
+    },
+    chat: {
+      assistantSetting: 'Assistant Setting',
+      promptEngine: 'Prompt Engine',
+      modelSetting: 'Model Setting',
+      chat: 'Chat',
+      newChat: 'New chat',
+      send: 'Send',
+      sendPlaceholder: 'Message Resume Assistant...',
+      chatConfiguration: 'Chat Configuration',
+      chatConfigurationDescription:
+        ' Here, dress up a dedicated assistant for your special knowledge bases! đź’•',
+      assistantName: 'Assistant name',
+      namePlaceholder: 'e.g. Resume Jarvis',
+      assistantAvatar: 'Assistant avatar',
+      language: 'Language',
+      emptyResponse: 'Empty response',
+      emptyResponseTip: `If nothing is retrieved with user's question in the knowledgebase, it will use this as an answer. If you want LLM comes up with its own opinion when nothing is retrieved, leave this blank.`,
+      setAnOpener: 'Set an opener',
+      setAnOpenerInitial: `Hi! I'm your assistant, what can I do for you?`,
+      setAnOpenerTip: 'How do you want to welcome your clients?',
+      knowledgeBases: 'Knowledgebases',
+      knowledgeBasesMessage: 'Please select',
+      knowledgeBasesTip: 'Select knowledgebases associated.',
+      system: 'System',
+      systemInitialValue: `You are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence "The answer you are looking for is not found in the knowledge base!" Answers need to consider chat history.
+      Here is the knowledge base:
+      {knowledge}
+      The above is the knowledge base.`,
+      systemMessage: 'Please input!',
+      systemTip:
+        'Instructions you need LLM to follow when LLM answers questions, like charactor design, answer length and answer language etc.',
+      topN: 'Top N',
+      topNTip: `Not all the chunks whose similarity score is above the 'simialrity threashold' will be feed to LLMs. LLM can only see these 'Top N' chunks.`,
+      variable: 'Variable',
+      variableTip: `If you use dialog APIs, the varialbes might help you chat with your clients with different strategies. 
+      The variables are used to fill-in the 'System' part in prompt in order to give LLM a hint.
+      The 'knowledge' is a very special variable which will be filled-in with the retrieved chunks.
+      All the variables in 'System' should be curly bracketed.`,
+      add: 'Add',
+      key: 'key',
+      optional: 'Optional',
+      operation: 'operation',
+      model: 'Model',
+      modelTip: 'Large language chat model',
+      modelMessage: 'Please select!',
+      freedom: 'Freedom',
+      improvise: 'Improvise',
+      precise: 'Precise',
+      balance: 'Balance',
+      freedomTip: `'Precise' means the LLM will be conservative and answer your question cautiously. 'Improvise' means the you want LLM talk much and freely. 'Balance' is between cautiously and freely.`,
+      temperature: 'Temperature',
+      temperatureMessage: 'Temperature is required',
+      temperatureTip:
+        'This parameter controls the randomness of predictions by the model. A lower temperature makes the model more confident in its responses, while a higher temperature makes it more creative and diverse.',
+      topP: 'Top P',
+      topPMessage: 'Top P is required',
+      topPTip:
+        'Also known as “nucleus sampling,” this parameter sets a threshold to select a smaller set of words to sample from. It focuses on the most likely words, cutting off the less probable ones.',
+      presencePenalty: 'Presence Penalty',
+      presencePenaltyMessage: 'Presence Penalty is required',
+      presencePenaltyTip:
+        'This discourages the model from repeating the same information by penalizing words that have already appeared in the conversation.',
+      frequencyPenalty: 'Frequency Penalty',
+      frequencyPenaltyMessage: 'Frequency Penalty is required',
+      frequencyPenaltyTip:
+        'Similar to the presence penalty, this reduces the model’s tendency to repeat the same words frequently.',
+      maxTokens: 'Max Tokens',
+      maxTokensMessage: 'Max Tokens is required',
+      maxTokensTip:
+        'This sets the maximum length of the model’s output, measured in the number of tokens (words or pieces of words).',
+    },
+    setting: {
+      profile: 'Profile',
+      profileDescription: 'Update your photo and personal details here.',
+      password: 'Password',
+      passwordDescription:
+        'Please enter your current password to change your password.',
+      model: 'Model Providers',
+      modelDescription: 'Manage your account settings and preferences here.',
+      team: 'Team',
+      logout: 'Log out',
+      username: 'Username',
+      usernameMessage: 'Please input your username!',
+      photo: 'Your photo',
+      photoDescription: 'This will be displayed on your profile.',
+      colorSchema: 'Color schema',
+      colorSchemaMessage: 'Please select your color schema!',
+      colorSchemaPlaceholder: 'select your color schema',
+      bright: 'Bright',
+      dark: 'Dark',
+      timezone: 'Timezone',
+      timezoneMessage: 'Please input your timezone!',
+      timezonePlaceholder: 'select your timezone',
+      email: 'Email address',
+      emailDescription: 'Once registered, E-mail cannot be changed.',
+      currentPassword: 'Current password',
+      currentPasswordMessage: 'Please input your password!',
+      newPassword: 'New password',
+      newPasswordMessage: 'Please input your password!',
+      newPasswordDescription:
+        'Your new password must be more than 8 characters.',
+      confirmPassword: 'Confirm new password',
+      confirmPasswordMessage: 'Please confirm your password!',
+      confirmPasswordNonMatchMessage:
+        'The new password that you entered do not match!',
+      cancel: 'Cancel',
+      addedModels: 'Added models',
+      modelsToBeAdded: 'Models to be added',
+      addTheModel: 'Add the model',
+      apiKey: 'API-Key',
+      apiKeyMessage: 'Please input api key!',
+      apiKeyTip:
+        'The API key can be obtained by registering the corresponding LLM supplier.',
+      showMoreModels: 'Show more models',
+      baseUrl: 'Base-Url',
+      baseUrlTip:
+        'If your API key is from OpenAI, just ignore it. Any other intermediate providers will give this base url with the API key.',
+      modify: 'Modify',
+      systemModelSettings: 'System Model Settings',
+      chatModel: 'Chat model',
+      chatModelTip:
+        'The default chat LLM all the newly created knowledgebase will use.',
+      embeddingModel: 'Embedding model',
+      embeddingModelTip:
+        'The default embedding model all the newly created knowledgebase will use.',
+      img2txtModel: 'Img2txt model',
+      img2txtModelTip:
+        'The default multi-module model all the newly created knowledgebase will use. It can describe a picture or video.',
+      sequence2txtModel: 'Img2txt model',
+      sequence2txtModelTip:
+        'The default ASR model all the newly created knowledgebase will use. Use this model to translate voices to corresponding text.',
+      workspace: 'Workspace',
+      upgrade: 'Upgrade',
+    },
+    message: {
+      registered: 'Registered!',
+      logout: 'logout',
+      logged: 'logged!',
+      pleaseSelectChunk: 'Please select chunk!',
+      modified: 'Modified',
+      created: 'Created',
+      deleted: 'Deleted',
+      renamed: 'Renamed',
+      operated: 'Operated',
+      updated: 'Updated',
+      200: 'The server successfully returns the requested data.',
+      201: 'Create or modify data successfully.',
+      202: 'A request has been queued in the background (asynchronous task).',
+      204: 'Data deleted successfully.',
+      400: 'There was an error in the request issued, and the server did not create or modify data.',
+      401: 'The user does not have permissions (wrong token, username, password).',
+      403: 'The user is authorized, but access is prohibited.',
+      404: 'The request was made for a record that does not exist, and the server did not perform the operation.',
+      406: 'The requested format is not available.',
+      410: 'The requested resource has been permanently deleted and will not be available again.',
+      422: 'When creating an object, a validation error occurred.',
+      500: 'A server error occurred, please check the server.',
+      502: 'Gateway error.',
+      503: 'The service is unavailable and the server is temporarily overloaded or undergoing maintenance.',
+      504: 'Gateway timeout.',
+      requestError: 'Request error',
+      networkAnomalyDescription:
+        'There is an abnormality in your network and you cannot connect to the server.',
+      networkAnomaly: 'network anomaly',
+      hint: 'hint',
+    },
+    footer: {
+      profile: 'All rights reserved @ React',
+    },
+    layout: {
+      file: 'file',
+      knowledge: 'knowledge',
+      chat: 'chat',
+    },
+  },
+};
diff --git a/web/src/locales/zh.json b/web/src/locales/zh.json
deleted file mode 100644
index a6fd83502aa23be3062461224673eb774aa0c502..0000000000000000000000000000000000000000
--- a/web/src/locales/zh.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-  "translation": {
-    "login": { "login": "登录" },
-    "header": {
-      "register": "注册",
-      "signin": "登陆",
-      "home": "首页",
-      "setting": "user setting",
-      "logout": "logout"
-    },
-    "footer": {
-      "detail": "版权所有 @ React"
-    },
-    "layout": {
-      "file": "文件",
-      "knowledge": "知识库",
-      "chat": "聊天"
-    },
-    "setting": {
-      "btn": "中文"
-    }
-  }
-}
diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts
new file mode 100644
index 0000000000000000000000000000000000000000..aa79895f697bd10e623c3ae9f255c09f78fb2bf3
--- /dev/null
+++ b/web/src/locales/zh.ts
@@ -0,0 +1,417 @@
+export default {
+  translation: {
+    common: {
+      delete: '删除',
+      deleteModalTitle: '确定删除吗?',
+      ok: '是',
+      cancel: '否',
+      total: '总共',
+      rename: '重命名',
+      name: '名称',
+      save: '保存',
+      namePlaceholder: '请输入名称',
+      next: '下一步',
+      create: '创建',
+      edit: '编辑',
+      upload: '上传',
+      english: '英文',
+      chinese: '中文',
+      language: '语言',
+      languageMessage: '请输入语言',
+      languagePlaceholder: '请选择语言',
+    },
+    login: {
+      login: '登录',
+      signUp: '注册',
+      loginDescription: '很高兴再次见到您!',
+      registerDescription: '很高兴您加入!',
+      emailLabel: '邮箱',
+      emailPlaceholder: '请输入邮箱地址',
+      passwordLabel: '密码',
+      passwordPlaceholder: '请输入密码',
+      rememberMe: '记住我',
+      signInTip: '没有帐户?',
+      signUpTip: '已经有帐户?',
+      nicknameLabel: '名称',
+      nicknamePlaceholder: '请输入名称',
+      register: '创建账户',
+      continue: '继续',
+      title: '开始构建您的智能助手',
+      description:
+        '免费注册以探索顶级 RAG 技术。 创建知识库和人工智能来增强您的业务',
+      review: '来自 500 多条评论',
+    },
+    header: {
+      knowledgeBase: '知识库',
+      chat: '聊天',
+      register: '注册',
+      signin: '登录',
+      home: '首页',
+      setting: '用户设置',
+      logout: '登出',
+    },
+    knowledgeList: {
+      welcome: '欢迎回来',
+      description: '今天我们要使用哪个知识库?',
+      createKnowledgeBase: '创建知识库',
+      name: '名称',
+      namePlaceholder: '请输入名称',
+      doc: '文档',
+    },
+    knowledgeDetails: {
+      dataset: '数据集',
+      testing: '检索测试',
+      configuration: 'é…Ťç˝®',
+      files: '文件',
+      name: '名称',
+      namePlaceholder: '请输入名称',
+      doc: '文档',
+      datasetDescription: '嘿,添加数据集后别忘了调整解析块! 😉',
+      addFile: '新增文件',
+      searchFiles: '搜索文件',
+      localFiles: '本地文件',
+      emptyFiles: '新建空文件',
+      chunkNumber: '模块数',
+      uploadDate: '上传日期',
+      chunkMethod: '解析方法',
+      enabled: '启用',
+      action: '动作',
+      parsingStatus: '解析状态',
+      processBeginAt: '流程开始于',
+      processDuration: '过程持续时间',
+      progressMsg: '进度消息',
+      testingDescription: '最后一步! 成功后,剩下的就交给Infiniflow AI吧。',
+      topK: 'Top K',
+      topKTip:
+        '对于计算成本,并非所有检索到的块都会计算与查询的向量余弦相似度。 Top K越大,召回率越高,检索速度越慢。',
+      similarityThreshold: '相似度阈值',
+      similarityThresholdTip:
+        '我们使用混合相似度得分来评估两行文本之间的距离。 它是加权关键词相似度和向量余弦相似度。 如果查询和块之间的相似度小于此阈值,则该块将被过滤掉。',
+      vectorSimilarityWeight: '向量相似度权重',
+      vectorSimilarityWeightTip:
+        '我们使用混合相似度得分来评估两行文本之间的距离。 它是加权关键词相似度和向量余弦相似度。 两个权重之和为 1.0。',
+      testText: '测试文本',
+      testTextPlaceholder: '请输入您的问题!',
+      testingLabel: '测试',
+      similarity: '混合相似度',
+      termSimilarity: '术语相似度',
+      vectorSimilarity: '向量相似度',
+      hits: '命中数',
+      view: 'çś‹ćł•',
+      filesSelected: '选定的文件',
+      upload: '上传',
+      runningStatus0: '未启动',
+      runningStatus1: '解析中',
+      runningStatus2: '取消',
+      runningStatus3: '成功',
+      runningStatus4: '失败',
+      pageRanges: '页码范围',
+      pageRangesTip:
+        '页码范围:定义需要解析的页面范围。 不包含在这些范围内的页面将被忽略。',
+      fromPlaceholder: '从',
+      fromMessage: '缺少起始页码',
+      toPlaceholder: '到',
+      toMessage: '缺少结束页码(不包含)',
+      layoutRecognize: '布局识别',
+      layoutRecognizeTip:
+        '使用视觉模型进行布局分析,以更好地识别文档结构,找到标题、文本块、图像和表格的位置。 如果没有此功能,则只能获取 PDF 的纯文本。',
+      taskPageSize: '任务页面大小',
+      taskPageSizeMessage: '请输入您的任务页面大小!',
+      taskPageSizeTip: `如果使用布局识别,PDF 文件将被分成连续的组。 布局分析将在组之间并行执行,以提高处理速度。 “任务页面大小”决定组的大小。 页面大小越大,将页面之间的连续文本分割成不同块的机会就越低。`,
+      addPage: '新增页面',
+      greaterThan: '当前值必须大于起始值!',
+      greaterThanPrevious: '当前值必须大于之前的值!',
+      selectFiles: '选择文件',
+      changeSpecificCategory: '更改特定类别',
+      uploadTitle: '点击或拖拽文件至此区域即可上传',
+      uploadDescription:
+        '支持单次或批量上传。 严禁上传公司数据或其他违禁文件。',
+    },
+    knowledgeConfiguration: {
+      titleDescription: '在这里更新您的知识库详细信息,尤其是解析方法。',
+      name: '知识库名称',
+      photo: '知识库图片',
+      description: '描述',
+      language: '语言',
+      languageMessage: '请输入语言',
+      languagePlaceholder: '请输入语言',
+      permissions: '权限',
+      embeddingModel: '嵌入模型',
+      chunkTokenNumber: '块令牌数',
+      chunkTokenNumberMessage: '块令牌数是必填项',
+      embeddingModelTip:
+        '用于嵌入块的嵌入模型。 一旦知识库有了块,它就无法更改。 如果你想改变它,你需要删除所有的块。',
+      permissionsTip: '如果权限是“团队”,则所有团队成员都可以操作知识库。',
+      chunkTokenNumberTip: '它大致确定了一个块的令牌数量。',
+      chunkMethod: '解析方法',
+      chunkMethodTip: '说明位于右侧。',
+      upload: '上传',
+      english: '英文',
+      chinese: '中文',
+      embeddingModelPlaceholder: '请选择嵌入模型',
+      chunkMethodPlaceholder: '请选择分块方法',
+      save: '保存',
+      me: '只有我',
+      team: '团队',
+      cancel: '取消',
+      methodTitle: '分块方法说明',
+      methodExamples: '示例',
+      methodExamplesDescription: '这个视觉指南是为了让您更容易理解。',
+      dialogueExamplesTitle: '对话示例',
+      methodEmpty: '这将显示知识库类别的可视化解释',
+      book: `<p>支持的文件格式为<b>DOCX</b>、<b>PDF</b>、<b>TXT</b>。</p><p>
+      由于一本书很长,并不是所有部分都有用,如果是 PDF,
+      请为每本书设置<i>页面范围</i>,以消除负面影响并节省分析计算时间。</p>`,
+      laws: `<p>支持的文件格式为<b>DOCX</b>、<b>PDF</b>、<b>TXT</b>。</p><p>
+      法律文件有非常严格的书写格式。 我们使用文本特征来检测分割点。
+      </p><p>
+      chunk的粒度与'ARTICLE'一致,所有上层文本都会包含在chunk中。
+      </p>`,
+      manual: `<p>仅支持<b>PDF</b>。</p><p>
+      我们假设手册具有分层部分结构。 我们使用最低的部分标题作为对文档进行切片的枢轴。
+      因此,同一部分中的图和表不会被分割,并且块大小可能会很大。
+      </p>`,
+      naive: `<p>支持的文件格式为<b>DOCX、EXCEL、PPT、IMAGE、PDF、TXT</b>。</p>
+      <p>此方法将简单的方法应用于块文件:</p>
+      <p>
+      <li>系统将使用视觉检测模型将连续文本分割成多个片段。</li>
+      <li>接下来,这些连续的片段被合并成令牌数不超过“令牌数”的块。</li></p>`,
+      paper: `<p>仅支持<b>PDF</b>文件。</p><p>
+      如果我们的模型运行良好,论文将按其部分进行切片,例如<i>摘要、1.1、1.2</i>等。</p><p>
+      这样做的好处是LLM可以更好的概括论文中相关章节的内容,
+      产生更全面的答案,帮助读者更好地理解论文。
+      缺点是它增加了 LLM 对话的背景并增加了计算成本,
+      所以在对话过程中,你可以考虑减少‘<b>topN</b>’的设置。</p>`,
+      presentation: `<p>支持的文件格式为<b>PDF</b>、<b>PPTX</b>。</p><p>
+      每个页面都将被视为一个块。 并且每个页面的缩略图都会被存储。</p><p>
+      <i>您上传的所有PPT文件都会使用此方法自动分块,无需为每个PPT文件进行设置。</i></p>`,
+      qa: `支持<p><b>EXCEL</b>和<b>CSV/TXT</b>文件。</p><p>
+      如果文件是Excel格式,应该有2列问题和答案,没有标题。
+      问题栏位于答案栏之前。
+      如果有多个工作表也没关系,只要列的组合正确即可。</p><p>
+   
+      如果是 csv 格式,则应采用 UTF-8 编码。 使用 TAB 作为分隔符来分隔问题和答案。</p><p>
+   
+      <i>所有变形的线都将被忽略。
+      每对问答都将被视为一个块。</i></p>`,
+      resume: `<p>支持的文件格式为<b>DOCX</b>、<b>PDF</b>、<b>TXT</b>。
+      </p><p>
+      简历有多种格式,就像一个人的个性一样,但我们经常必须将它们组织成结构化数据,以便于搜索。
+      </p><p>
+      我们不是将简历分块,而是将简历解析为结构化数据。 作为HR,你可以扔掉所有的简历,
+      您只需与<i>'RAGFlow'</i>交谈即可列出所有符合资格的候选人。
+      </p>
+        `,
+      table: `支持<p><b>EXCEL</b>和<b>CSV/TXT</b>格式文件。</p><p>
+      以下是一些提示:
+      <ul>
+    <li>对于 csv 或 txt 文件,列之间的分隔符为 <em><b>TAB</b></em>。</li>
+    <li>第一行必须是列标题。</li>
+    <li>列标题必须是有意义的术语,以便我们的法学硕士能够理解。
+    列举一些同义词时最好使用斜杠<i>'/'</i>来分隔,甚至更好
+    使用方括号枚举值,例如 <i>'gender/sex(male,female)'</i>.<p>
+    以下是标题的一些示例:<ol>
+        <li>供应商/供货商<b>'TAB'</b>颜色(黄色、红色、棕色)<b>'TAB'</b>性别(男、女)<b>'TAB'</ b>尺码(M、L、XL、XXL)</li>
+        <li>姓名/名字<b>'TAB'</b>电话/手机/微信<b>'TAB'</b>最高学历(高中,职高,硕士,本科,博士,初中,中技,中 专,专科,专升本,MPA,MBA,EMBA)</li>
+        </ol>
+        </p>
+    </li>
+    <li>表中的每一行都将被视为一个块。</li>
+    </ul>`,
+      picture: `
+      <p>支持图像文件。 视频即将推出。</p><p>
+      如果图片中有文字,则应用 OCR 提取文字作为其文字描述。
+      </p><p>
+      如果OCR提取的文本不够,可以使用视觉LLM来获取描述。
+      </p>`,
+      one: `
+      <p>支持的文件格式为<b>DOCX、EXCEL、PDF、TXT</b>。
+      </p><p>
+      对于一个文档,它将被视为一个完整的块,根本不会被分割。
+      </p><p>
+      如果你要总结的东西需要一篇文章的全部上下文,并且所选LLM的上下文长度覆盖了文档长度,你可以尝试这种方法。
+      </p>`,
+    },
+    chunk: {
+      chunk: '解析块',
+      bulk: '批量',
+      selectAll: '选择所有',
+      enabledSelected: '启用选定的',
+      disabledSelected: '禁用选定的',
+      deleteSelected: '删除选定的',
+      search: '搜索',
+      all: '所有',
+      enabled: '启用',
+      disabled: '禁用的',
+      keyword: '关键词',
+      function: '函数',
+      chunkMessage: '请输入值!',
+    },
+    chat: {
+      assistantSetting: '助理设置',
+      promptEngine: '提示引擎',
+      modelSetting: '模型设置',
+      chat: '聊天',
+      newChat: '新建聊天',
+      send: '发送',
+      sendPlaceholder: '消息概要助手...',
+      chatConfiguration: '聊天配置',
+      chatConfigurationDescription: '在这里,为你的专业知识库装扮专属助手! 💕',
+      assistantName: '助理姓名',
+      namePlaceholder: '例如 贾维斯简历',
+      assistantAvatar: '助理头像',
+      language: '语言',
+      emptyResponse: '空回复',
+      emptyResponseTip: `如果在知识库中没有检索到用户的问题,它将使用它作为答案。 如果您希望 LLM 在未检索到任何内容时提出自己的意见,请将此留空。`,
+      setAnOpener: '设置开场白',
+      setAnOpenerInitial: `你好! 我是你的助理,有什么可以帮到你的吗?`,
+      setAnOpenerTip: '您想如何欢迎您的客户?',
+      knowledgeBases: '知识库',
+      knowledgeBasesMessage: '请选择',
+      knowledgeBasesTip: '选择关联的知识库。',
+      system: '系统',
+      systemInitialValue: `你是一个智能助手,请总结知识库的内容来回答问题,请列举知识库中的数据详细回答。当所有知识库内容都与问题无关时,你的回答必须包括“知识库中未找到您要的答案!”这句话。回答需要考虑聊天历史。
+        以下是知识库:
+        {knowledge}
+        以上是知识库。`,
+      systemMessage: '请输入',
+      systemTip:
+        '当LLM回答问题时,你需要LLM遵循的说明,比如角色设计、答案长度和答案语言等。',
+      topN: 'Top N',
+      topNTip: `并非所有相似度得分高于“相似度阈值”的块都会被提供给法学硕士。 LLM 只能看到这些“Top N”块。`,
+      variable: '变量',
+      variableTip: `如果您使用对话 API,变量可能会帮助您使用不同的策略与客户聊天。
+      这些变量用于填写提示中的“系统”部分,以便给LLM一个提示。
+      “知识”是一个非常特殊的变量,它将用检索到的块填充。
+      “System”中的所有变量都应该用大括号括起来。`,
+      add: '新增',
+      key: '关键字',
+      optional: '可选的',
+      operation: '操作',
+      model: '模型',
+      modelTip: '大语言聊天模型',
+      modelMessage: '请选择',
+      freedom: '自由',
+      improvise: '即兴创作',
+      precise: '精确',
+      balance: '平衡',
+      freedomTip: `“精确”意味着法学硕士会保守并谨慎地回答你的问题。 “即兴发挥”意味着你希望法学硕士能够自由地畅所欲言。 “平衡”是谨慎与自由之间的平衡。`,
+      temperature: '温度',
+      temperatureMessage: '温度是必填项',
+      temperatureTip:
+        '该参数控制模型预测的随机性。 较低的温度使模型对其响应更有信心,而较高的温度则使其更具创造性和多样性。',
+      topP: 'Top P',
+      topPMessage: 'Top P 是必填项',
+      topPTip:
+        '该参数也称为“核心采样”,它设置一个阈值来选择较小的单词集进行采样。 它专注于最可能的单词,剔除不太可能的单词。',
+      presencePenalty: '出席处罚',
+      presencePenaltyMessage: '出席处罚是必填项',
+      presencePenaltyTip:
+        '这会通过惩罚对话中已经出现的单词来阻止模型重复相同的信息。',
+      frequencyPenalty: '频率惩罚',
+      frequencyPenaltyMessage: '频率惩罚是必填项',
+      frequencyPenaltyTip:
+        '与存在惩罚类似,这减少了模型频繁重复相同单词的倾向。',
+      maxTokens: '最大token数',
+      maxTokensMessage: '最大token数是必填项',
+      maxTokensTip:
+        '这设置了模型输出的最大长度,以标记(单词或单词片段)的数量来衡量。',
+    },
+    setting: {
+      profile: '概要',
+      profileDescription: '在此更新您的照片和个人详细信息。',
+      password: '密码',
+      passwordDescription: '请输入您当前的密码以更改您的密码。',
+      model: '模型提供商',
+      modelDescription: '在此管理您的帐户设置和首选项。',
+      team: '团队',
+      logout: '登出',
+      username: '用户名',
+      usernameMessage: '请输入用户名',
+      photo: '头像',
+      photoDescription: '这将显示在您的个人资料上。',
+      colorSchema: '主题',
+      colorSchemaMessage: '请选择您的主题!',
+      colorSchemaPlaceholder: '请选择您的主题!',
+      bright: '明亮',
+      dark: '暗色',
+      timezone: '时区',
+      timezoneMessage: '请选择时区',
+      timezonePlaceholder: '请选择时区',
+      email: '邮箱地址',
+      emailDescription: '一旦注册,电子邮件将无法更改。',
+      currentPassword: '当前密码',
+      currentPasswordMessage: '请输入当前密码',
+      newPassword: '新密码',
+      newPasswordMessage: '请输入新密码',
+      newPasswordDescription: '您的新密码必须超过 8 个字符。',
+      confirmPassword: '确认新密码',
+      confirmPasswordMessage: '请确认新密码',
+      confirmPasswordNonMatchMessage: '您输入的新密码不匹配!',
+      cancel: '取消',
+      addedModels: '添加了的模型',
+      modelsToBeAdded: '待添加的模型',
+      addTheModel: '添加模型',
+      apiKey: 'API-Key',
+      apiKeyMessage: '请输入 api key!',
+      apiKeyTip: 'API key可以通过注册相应的LLM供应商来获取。',
+      showMoreModels: '展示更多模型',
+      baseUrl: 'Base-Url',
+      baseUrlTip:
+        '如果您的 API 密钥来自 OpenAI,请忽略它。 任何其他中间提供商都会提供带有 API 密钥的基本 URL。',
+      modify: '修改',
+      systemModelSettings: '系统模型设置',
+      chatModel: '聊天模型',
+      chatModelTip: '所有新创建的知识库都会使用默认的聊天LLM。',
+      embeddingModel: '嵌入模型',
+      embeddingModelTip: '所有新创建的知识库都将使用的默认嵌入模型。',
+      img2txtModel: 'Img2txt模型',
+      img2txtModelTip:
+        '所有新创建的知识库都将使用默认的多模块模型。 它可以描述图片或视频。',
+      sequence2txtModel: 'Img2txt模型',
+      sequence2txtModelTip:
+        '所有新创建的知识库都将使用默认的 ASR 模型。 使用此模型将语音翻译为相应的文本。',
+      workspace: '工作空间',
+      upgrade: '升级',
+    },
+    message: {
+      registered: '注册成功',
+      logout: '登出成功',
+      logged: '登录成功',
+      pleaseSelectChunk: '请选择解析块',
+      modified: '更新成功',
+      created: '创建成功',
+      deleted: '删除成功',
+      renamed: '重命名成功',
+      operated: '操作成功',
+      updated: '更新成功',
+      200: '服务器成功返回请求的数据。',
+      201: '新建或修改数据成功。',
+      202: '一个请求已经进入后台排队(异步任务)。',
+      204: '删除数据成功。',
+      400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
+      401: '用户没有权限(令牌、用户名、密码错误)。',
+      403: '用户得到授权,但是访问是被禁止的。',
+      404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
+      406: '请求的格式不可得。',
+      410: '请求的资源被永久删除,且不会再得到的。',
+      422: '当创建一个对象时,发生一个验证错误。',
+      500: '服务器发生错误,请检查服务器。',
+      502: '网关错误。',
+      503: '服务不可用,服务器暂时过载或维护。',
+      504: '网关超时。',
+      requestError: '请求错误',
+      networkAnomalyDescription: '您的网络发生异常,无法连接服务器',
+      networkAnomaly: '网络异常',
+      hint: '提示',
+    },
+    footer: {
+      profile: 'All rights reserved @ React',
+    },
+    layout: {
+      file: 'file',
+      knowledge: 'knowledge',
+      chat: 'chat',
+    },
+  },
+};
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-creating-modal/index.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-creating-modal/index.tsx
index 15f84ac2dd4a0a58a265881150b32ba890df775b..93f2382ac7d925bf3dfc0e4495e025ff2ecd23c6 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-creating-modal/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-creating-modal/index.tsx
@@ -3,6 +3,7 @@ import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
 import { DeleteOutlined } from '@ant-design/icons';
 import { Checkbox, Form, Input, Modal, Space } from 'antd';
 import React, { useCallback, useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
 import { useDispatch, useSelector } from 'umi';
 import EditTag from '../edit-tag';
 
@@ -24,6 +25,7 @@ const ChunkCreatingModal: React.FC<kFProps> = ({ doc_id, chunkId }) => {
   const [keywords, setKeywords] = useState<string[]>([]);
   const loading = useOneNamespaceEffectsLoading('chunkModel', ['create_chunk']);
   const { removeChunk } = useDeleteChunkByIds();
+  const { t } = useTranslation();
 
   const handleCancel = () => {
     dispatch({
@@ -87,7 +89,7 @@ const ChunkCreatingModal: React.FC<kFProps> = ({ doc_id, chunkId }) => {
 
   return (
     <Modal
-      title={`${chunkId ? 'Edit' : 'Create'} Chunk`}
+      title={`${chunkId ? t('common.edit') : t('common.create')} ${t('chunk.chunk')}`}
       open={isShowCreateModal}
       onOk={handleOk}
       onCancel={handleCancel}
@@ -100,27 +102,27 @@ const ChunkCreatingModal: React.FC<kFProps> = ({ doc_id, chunkId }) => {
         layout={'vertical'}
       >
         <Form.Item<FieldType>
-          label="Chunk"
+          label={t('chunk.chunk')}
           name="content"
-          rules={[{ required: true, message: 'Please input value!' }]}
+          rules={[{ required: true, message: t('chunk.chunkMessage') }]}
         >
           <Input.TextArea autoSize={{ minRows: 4, maxRows: 10 }} />
         </Form.Item>
       </Form>
       <section>
-        <p>Keyword*</p>
+        <p>{t('chunk.keyword')} *</p>
         <EditTag tags={keywords} setTags={setKeywords} />
       </section>
       {chunkId && (
         <section>
-          <p>Function*</p>
+          <p>{t('chunk.function')} *</p>
           <Space size={'large'}>
             <Checkbox onChange={handleCheck} checked={checked}>
-              Enabled
+              {t('chunk.enabled')}
             </Checkbox>
 
             <span onClick={handleRemove}>
-              <DeleteOutlined /> Delete
+              <DeleteOutlined /> {t('common.delete')}
             </span>
           </Space>
         </section>
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-toolbar/index.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-toolbar/index.tsx
index fd02a1b1046f3108b4d8f8aa3f45d144fa482c4f..ead23c48c8bb5d7c88814bff3af1cd3e8e627688 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-toolbar/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-toolbar/index.tsx
@@ -1,5 +1,6 @@
 import { ReactComponent as FilterIcon } from '@/assets/filter.svg';
 import { KnowledgeRouteKey } from '@/constants/knowledge';
+import { useTranslate } from '@/hooks/commonHooks';
 import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
 import {
   ArrowLeftOutlined,
@@ -49,6 +50,7 @@ const ChunkToolBar = ({
   const dispatch = useDispatch();
   const knowledgeBaseId = useKnowledgeBaseId();
   const [isShowSearchBox, setIsShowSearchBox] = useState(false);
+  const { t } = useTranslate('chunk');
 
   const handleSelectAllCheck = useCallback(
     (e: any) => {
@@ -95,7 +97,7 @@ const ChunkToolBar = ({
         label: (
           <>
             <Checkbox onChange={handleSelectAllCheck} checked={checked}>
-              <b>Select All</b>
+              <b>{t('selectAll')}</b>
             </Checkbox>
           </>
         ),
@@ -106,7 +108,7 @@ const ChunkToolBar = ({
         label: (
           <Space onClick={handleEnabledClick}>
             <CheckCircleOutlined />
-            <b>Enabled Selected</b>
+            <b>{t('enabledSelected')}</b>
           </Space>
         ),
       },
@@ -115,7 +117,7 @@ const ChunkToolBar = ({
         label: (
           <Space onClick={handleDisabledClick}>
             <CloseCircleOutlined />
-            <b>Disabled Selected</b>
+            <b>{t('disabledSelected')}</b>
           </Space>
         ),
       },
@@ -125,7 +127,7 @@ const ChunkToolBar = ({
         label: (
           <Space onClick={handleDelete}>
             <DeleteOutlined />
-            <b>Delete Selected</b>
+            <b>{t('deleteSelected')}</b>
           </Space>
         ),
       },
@@ -136,6 +138,7 @@ const ChunkToolBar = ({
     handleDelete,
     handleEnabledClick,
     handleDisabledClick,
+    t,
   ]);
 
   const content = (
@@ -151,9 +154,9 @@ const ChunkToolBar = ({
   const filterContent = (
     <Radio.Group onChange={handleFilterChange} value={available}>
       <Space direction="vertical">
-        <Radio value={undefined}>All</Radio>
-        <Radio value={1}>Enabled</Radio>
-        <Radio value={0}>Disabled</Radio>
+        <Radio value={undefined}>{t('all')}</Radio>
+        <Radio value={1}>{t('enabled')}</Radio>
+        <Radio value={0}>{t('disabled')}</Radio>
       </Space>
     </Radio.Group>
   );
@@ -172,14 +175,14 @@ const ChunkToolBar = ({
       <Space>
         <Popover content={content} placement="bottom" arrow={false}>
           <Button>
-            Bulk
+            {t('bulk')}
             <DownOutlined />
           </Button>
         </Popover>
         {isShowSearchBox ? (
           <Input
             size="middle"
-            placeholder="Search"
+            placeholder={t('search')}
             prefix={<SearchOutlined />}
             allowClear
             onChange={handleSearchChange}
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
index d63e70e39b62cf7bc0d9651e058fb86fbcbc59ed..dc6029199a0e3aff2d673bc49c866aa55e8a6b06 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
@@ -16,6 +16,7 @@ import {
 } from './hooks';
 import { ChunkModelState } from './model';
 
+import { useTranslation } from 'react-i18next';
 import styles from './index.less';
 
 const Chunk = () => {
@@ -33,6 +34,7 @@ const Chunk = () => {
   const documentInfo = useSelectDocumentInfo();
   const { handleChunkCardClick, selectedChunkId } = useHandleChunkCardClick();
   const isPdf = documentInfo.type === 'pdf';
+  const { t } = useTranslation();
 
   const getChunkList = useFetchChunkList();
 
@@ -86,7 +88,7 @@ const Chunk = () => {
     [],
   );
   const showSelectedChunkWarning = () => {
-    message.warning('Please select chunk!');
+    message.warning(t('message.pleaseSelectChunk'));
   };
 
   const handleRemoveChunk = useCallback(async () => {
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts b/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
index 5d9089a983dca5bfaa8857f8865a8cc8eb4f00fa..93187b15f7b9dd8bb73ce3c8bb72eca5b906ec9c 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
@@ -4,6 +4,7 @@ import kbService from '@/services/kbService';
 import { message } from 'antd';
 import { pick } from 'lodash';
 // import { delay } from '@/utils/storeUtil';
+import i18n from '@/locales/config';
 import { DvaModel } from 'umi';
 
 export interface ChunkModelState extends BaseState {
@@ -102,7 +103,7 @@ const model: DvaModel<ChunkModelState> = {
       const { data } = yield call(kbService.switch_chunk, payload);
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Modified successfully !');
+        message.success(i18n.t('message.modified'));
       }
       return retcode;
     },
diff --git a/web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx b/web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx
index aaff97ccd221dabc91d84554e212520828b9c5b5..263457a757515cd53371b9e866aa72a1ba8539fd 100644
--- a/web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx
@@ -40,6 +40,7 @@ import classNames from 'classnames';
 import { ReactElement, useCallback, useMemo, useRef, useState } from 'react';
 import { Link, useNavigate } from 'umi';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import styles from './index.less';
 
 const { Dragger } = Upload;
@@ -135,6 +136,7 @@ const KnowledgeUploadFile = () => {
   const documentList = useSelectDocumentList();
   const runDocumentByIds = useRunDocument();
   const uploadDocument = useUploadDocument();
+  const { t } = useTranslate('knowledgeDetails');
 
   const enabled = useMemo(() => {
     if (isUpload) {
@@ -257,10 +259,10 @@ const KnowledgeUploadFile = () => {
             </Flex>
             <Flex justify="space-around">
               <p className={styles.selectFilesText}>
-                <b>Select files</b>
+                <b>{t('selectFiles')}</b>
               </p>
               <p className={styles.changeSpecificCategoryText}>
-                <b>Change specific category</b>
+                <b>{t('changeSpecificCategory')}</b>
               </p>
             </Flex>
           </div>
@@ -275,13 +277,8 @@ const KnowledgeUploadFile = () => {
             <Button className={styles.uploaderButton}>
               <CloudUploadOutlined className={styles.uploaderIcon} />
             </Button>
-            <p className="ant-upload-text">
-              Click or drag file to this area to upload
-            </p>
-            <p className="ant-upload-hint">
-              Support for a single or bulk upload. Strictly prohibited from
-              uploading company data or other banned files.
-            </p>
+            <p className="ant-upload-text">{t('uploadTitle')}</p>
+            <p className="ant-upload-hint">{t('uploadDescription')}</p>
           </Dragger>
         </section>
         <section className={styles.footer}>
@@ -292,7 +289,7 @@ const KnowledgeUploadFile = () => {
             disabled={!enabled}
             size="large"
           >
-            Next
+            {t('next', { keyPrefix: 'common' })}
           </Button>
         </section>
       </div>
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx
index a520a90db91831e9a83e793eeffa4df5dbdfe012..096b22de4ee0eeaaf44439124787c1c9759810b2 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx
@@ -204,7 +204,9 @@ const KnowledgeFile = () => {
       <div className={styles.filter}>
         <Space>
           <h3>{t('total', { keyPrefix: 'common' })}</h3>
-          <Tag color="purple">{total} files</Tag>
+          <Tag color="purple">
+            {total} {t('files')}
+          </Tag>
         </Space>
         <Space>
           <Input
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/model.ts b/web/src/pages/add-knowledge/components/knowledge-file/model.ts
index f946c9d78893c4c2b61b4218cde76f8bb8e49ceb..490fa8533d00372f9690a726ee3efdd9f9aa8b36 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/model.ts
+++ b/web/src/pages/add-knowledge/components/knowledge-file/model.ts
@@ -1,5 +1,6 @@
 import { BaseState } from '@/interfaces/common';
 import { IKnowledgeFile } from '@/interfaces/database/knowledge';
+import i18n from '@/locales/config';
 import kbService, { getDocumentFile } from '@/services/kbService';
 import { message } from 'antd';
 import omit from 'lodash/omit';
@@ -54,14 +55,14 @@ const model: DvaModel<KFModelState> = {
       const { data } = yield call(kbService.createKb, payload);
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Created!');
+        message.success(i18n.t('message.created'));
       }
     },
     *updateKf({ payload = {} }, { call }) {
       const { data } = yield call(kbService.updateKb, payload);
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Modified!');
+        message.success(i18n.t('message.modified'));
       }
     },
     *getKfDetail({ payload = {} }, { call }) {
@@ -109,7 +110,7 @@ const model: DvaModel<KFModelState> = {
       );
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Modified!');
+        message.success(i18n.t('message.modified'));
         yield put({
           type: 'getKfList',
           payload: { kb_id: payload.kb_id },
@@ -122,7 +123,7 @@ const model: DvaModel<KFModelState> = {
       });
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Deleted!');
+        message.success(i18n.t('message.deleted'));
         yield put({
           type: 'getKfList',
           payload: { kb_id: payload.kb_id },
@@ -137,7 +138,7 @@ const model: DvaModel<KFModelState> = {
       );
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('rename success!');
+        message.success(i18n.t('message.renamed'));
 
         yield put({
           type: 'getKfList',
@@ -156,7 +157,7 @@ const model: DvaModel<KFModelState> = {
           payload: { kb_id: payload.kb_id },
         });
 
-        message.success('Created!');
+        message.success(i18n.t('message.created'));
       }
       return retcode;
     },
@@ -173,7 +174,7 @@ const model: DvaModel<KFModelState> = {
             payload: { kb_id: payload.knowledgeBaseId },
           });
         }
-        message.success('Operation successfully !');
+        message.success(i18n.t('message.operated'));
       }
       return retcode;
     },
@@ -189,7 +190,7 @@ const model: DvaModel<KFModelState> = {
           payload: { kb_id: payload.kb_id },
         });
 
-        message.success('Modified!');
+        message.success(i18n.t('message.modified'));
       }
       return retcode;
     },
diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx
index aa6c58659a7beb3051c1e20f540615e20717d823..d5ca83e888d6f3a6438136379265095144df6323 100644
--- a/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx
@@ -4,6 +4,7 @@ import { useTranslate } from '@/hooks/commonHooks';
 import { IKnowledgeFile } from '@/interfaces/database/knowledge';
 import { CloseCircleOutlined } from '@ant-design/icons';
 import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd';
+import { useTranslation } from 'react-i18next';
 import reactStringReplace from 'react-string-replace';
 import { useDispatch } from 'umi';
 import { RunningStatus, RunningStatusMap } from '../constant';
@@ -80,11 +81,14 @@ export const ParsingStatusCell = ({ record }: IProps) => {
   const dispatch = useDispatch();
   const text = record.run;
   const runningStatus = RunningStatusMap[text];
+  const { t } = useTranslation();
 
   const isRunning = isParserRunning(text);
 
   const OperationIcon = iconMap[text];
 
+  const label = t(`knowledgeDetails.runningStatus${text}`);
+
   const handleOperationIconClick = () => {
     dispatch({
       type: 'kFModel/document_run',
@@ -103,11 +107,11 @@ export const ParsingStatusCell = ({ record }: IProps) => {
           {isRunning ? (
             <Space>
               <Badge color={runningStatus.color} />
-              {runningStatus.label}
+              {label}
               <span>{(record.progress * 100).toFixed(2)}%</span>
             </Space>
           ) : (
-            runningStatus.label
+            label
           )}
         </Tag>
       </Popover>
diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/category-panel.tsx b/web/src/pages/add-knowledge/components/knowledge-setting/category-panel.tsx
index 8b6168e814ee1a5426ee86c18fc7e6422e1918c6..d7f6a6c5163e15fc0ea13d7628b156cadc284f91 100644
--- a/web/src/pages/add-knowledge/components/knowledge-setting/category-panel.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-setting/category-panel.tsx
@@ -1,25 +1,27 @@
 import SvgIcon from '@/components/svg-icon';
+import { useTranslate } from '@/hooks/commonHooks';
 import { useSelectParserList } from '@/hooks/userSettingHook';
 import { Col, Divider, Empty, Row, Typography } from 'antd';
 import { useMemo } from 'react';
 import styles from './index.less';
-import { ImageMap, TextMap } from './utils';
+import { ImageMap } from './utils';
 
 const { Title, Text } = Typography;
 
 const CategoryPanel = ({ chunkMethod }: { chunkMethod: string }) => {
   const parserList = useSelectParserList();
+  const { t } = useTranslate('knowledgeConfiguration');
 
   const item = useMemo(() => {
     const item = parserList.find((x) => x.value === chunkMethod);
     if (item) {
       return {
         title: item.label,
-        description: TextMap[item.value as keyof typeof TextMap]?.description,
+        description: t(item.value),
       };
     }
     return { title: '', description: '' };
-  }, [parserList, chunkMethod]);
+  }, [parserList, chunkMethod, t]);
 
   const imageList = useMemo(() => {
     if (chunkMethod in ImageMap) {
@@ -33,18 +35,17 @@ const CategoryPanel = ({ chunkMethod }: { chunkMethod: string }) => {
       {imageList.length > 0 ? (
         <>
           <Title level={5} className={styles.topTitle}>
-            "{item.title}" Chunking Method Description
+            "{item.title}" {t('methodTitle')}
           </Title>
           <p
             dangerouslySetInnerHTML={{
               __html: item.description,
             }}
           ></p>
-          <Title level={5}>"{item.title}" Examples</Title>
-          <Text>
-            This visual guides is in order to make understanding easier
-            for you.
-          </Text>
+          <Title level={5}>
+            "{item.title}" {t('methodExamples')}
+          </Title>
+          <Text>{t('methodExamplesDescription')}</Text>
           <Row gutter={[10, 10]} className={styles.imageRow}>
             {imageList.map((x) => (
               <Col span={12} key={x}>
@@ -56,15 +57,14 @@ const CategoryPanel = ({ chunkMethod }: { chunkMethod: string }) => {
               </Col>
             ))}
           </Row>
-          <Title level={5}>{item.title} Dialogue Examples</Title>
+          <Title level={5}>
+            {item.title} {t('dialogueExamplesTitle')}
+          </Title>
           <Divider></Divider>
         </>
       ) : (
         <Empty description={''} image={null}>
-          <p>
-            This will display a visual explanation of the knowledge base
-            categories
-          </p>
+          <p>{t('methodEmpty')}</p>
           <SvgIcon name={'chunk-method/chunk-empty'} width={'100%'}></SvgIcon>
         </Empty>
       )}
diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx b/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx
index b55164c176f367a2b7ff8ab0023f0c62c3573b0d..e50156ebf1c0ad52a1196387754dc55a3a4f6afa 100644
--- a/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx
@@ -59,7 +59,7 @@ const ConfigurationForm = ({ form }: { form: FormInstance }) => {
       </Form.Item>
       <Form.Item
         name="permission"
-        label="Permissions"
+        label={t('permissions')}
         tooltip={t('permissionsTip')}
         rules={[{ required: true }]}
       >
@@ -70,7 +70,7 @@ const ConfigurationForm = ({ form }: { form: FormInstance }) => {
       </Form.Item>
       <Form.Item
         name="embd_id"
-        label="Embedding model"
+        label={t('embeddingModel')}
         rules={[{ required: true }]}
         tooltip={t('embeddingModelTip')}
       >
@@ -82,7 +82,7 @@ const ConfigurationForm = ({ form }: { form: FormInstance }) => {
       </Form.Item>
       <Form.Item
         name="parser_id"
-        label="Chunk method"
+        label={t('chunkMethod')}
         tooltip={t('chunkMethodTip')}
         rules={[{ required: true }]}
       >
diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/model.ts b/web/src/pages/add-knowledge/components/knowledge-setting/model.ts
index a24aea8f44a2c4683256aede1277a9bd51fb4cb4..a2eb9e11840dcb6f3adac41e1dda6baa1c2e4aba 100644
--- a/web/src/pages/add-knowledge/components/knowledge-setting/model.ts
+++ b/web/src/pages/add-knowledge/components/knowledge-setting/model.ts
@@ -1,4 +1,5 @@
 import { IKnowledge } from '@/interfaces/database/knowledge';
+import i18n from '@/locales/config';
 import kbService from '@/services/kbService';
 import { message } from 'antd';
 import { DvaModel } from 'umi';
@@ -32,7 +33,7 @@ const model: DvaModel<KSModelState> = {
       const { data } = yield call(kbService.createKb, payload);
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Created!');
+        message.success(i18n.t('message.created'));
       }
       return data;
     },
@@ -41,7 +42,7 @@ const model: DvaModel<KSModelState> = {
       const { retcode } = data;
       if (retcode === 0) {
         yield put({ type: 'getKbDetail', payload: { kb_id: payload.kb_id } });
-        message.success('Updated!');
+        message.success(i18n.t('message.updated'));
       }
     },
     *getKbDetail({ payload = {} }, { call, put }) {
diff --git a/web/src/pages/add-knowledge/index.tsx b/web/src/pages/add-knowledge/index.tsx
index abe0e2e2bef55cdf0d2026b4061260b25ada9f31..68df6039955883bb6187698a69d9b8c137764bc8 100644
--- a/web/src/pages/add-knowledge/index.tsx
+++ b/web/src/pages/add-knowledge/index.tsx
@@ -14,7 +14,6 @@ import {
   KnowledgeDatasetRouteKey,
   KnowledgeRouteKey,
   datasetRouteMap,
-  routeMap,
 } from './constant';
 import styles from './index.less';
 
@@ -49,7 +48,7 @@ const KnowledgeAdding = () => {
             {t(`knowledgeDetails.${activeKey}`)}
           </Link>
         ) : (
-          routeMap[activeKey]
+          t(`knowledgeDetails.${activeKey}`)
         ),
       },
     ];
diff --git a/web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx b/web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx
index bca69b661d7d1520386fa955e2fe3c17c003865f..4dfdfe6cb5a7caeb9b5036d6d06ad6121bf84275 100644
--- a/web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx
+++ b/web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx
@@ -4,6 +4,7 @@ import { Form, Input, Select, Upload } from 'antd';
 import classNames from 'classnames';
 import { ISegmentedContentProps } from '../interface';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import styles from './index.less';
 
 const AssistantSetting = ({ show }: ISegmentedContentProps) => {
@@ -12,6 +13,7 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
     label: x.name,
     value: x.id,
   }));
+  const { t } = useTranslate('chat');
 
   const normFile = (e: any) => {
     if (Array.isArray(e)) {
@@ -28,14 +30,14 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
     >
       <Form.Item
         name={'name'}
-        label="Assistant name"
+        label={t('assistantName')}
         rules={[{ required: true }]}
       >
         <Input placeholder="e.g. Resume Jarvis" />
       </Form.Item>
       <Form.Item
         name="icon"
-        label="Assistant avatar"
+        label={t('assistantAvatar')}
         valuePropName="fileList"
         getValueFromEvent={normFile}
       >
@@ -46,44 +48,45 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
         >
           <button style={{ border: 0, background: 'none' }} type="button">
             <PlusOutlined />
-            <div style={{ marginTop: 8 }}>Upload</div>
+            <div style={{ marginTop: 8 }}>
+              {t('upload', { keyPrefix: 'common' })}
+            </div>
           </button>
         </Upload>
       </Form.Item>
       <Form.Item
         name={'language'}
-        label="Language"
+        label={t('language')}
         initialValue={'Chinese'}
         tooltip="coming soon"
-        style={{display:'none'}}
+        style={{ display: 'none' }}
       >
         <Select
           options={[
-            { value: 'Chinese', label: 'Chinese' },
-            { value: 'English', label: 'English' },
+            { value: 'Chinese', label: t('chinese', { keyPrefix: 'common' }) },
+            { value: 'English', label: t('english', { keyPrefix: 'common' }) },
           ]}
         />
       </Form.Item>
       <Form.Item
         name={['prompt_config', 'empty_response']}
-        label="Empty response"
-        tooltip="If nothing is retrieved with user's question in the knowledgebase, it will use this as an answer.
-        If you want LLM comes up with its own opinion when nothing is retrieved, leave this blank."
+        label={t('emptyResponse')}
+        tooltip={t('emptyResponseTip')}
       >
         <Input placeholder="" />
       </Form.Item>
       <Form.Item
         name={['prompt_config', 'prologue']}
-        label="Set an opener"
-        tooltip="How do you want to welcome your clients?"
-        initialValue={"Hi! I'm your assistant, what can I do for you?"}
+        label={t('setAnOpener')}
+        tooltip={t('setAnOpenerTip')}
+        initialValue={t('setAnOpenerInitial')}
       >
         <Input.TextArea autoSize={{ minRows: 5 }} />
       </Form.Item>
       <Form.Item
-        label="Knowledgebases"
+        label={t('knowledgeBases')}
         name="kb_ids"
-        tooltip="Select knowledgebases associated."
+        tooltip={t('knowledgeBasesTip')}
         rules={[
           {
             required: true,
@@ -95,7 +98,7 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
         <Select
           mode="multiple"
           options={knowledgeOptions}
-          placeholder="Please select"
+          placeholder={t('knowledgeBasesMessage')}
         ></Select>
       </Form.Item>
     </section>
diff --git a/web/src/pages/chat/chat-configuration-modal/index.tsx b/web/src/pages/chat/chat-configuration-modal/index.tsx
index 91281e56ce22ec48a1ae985a22ed6e61da9bcf4d..8ddec396f78a58b8af5d97376b9b852d301acbed 100644
--- a/web/src/pages/chat/chat-configuration-modal/index.tsx
+++ b/web/src/pages/chat/chat-configuration-modal/index.tsx
@@ -7,6 +7,7 @@ import {
 import { IDialog } from '@/interfaces/database/chat';
 import { Divider, Flex, Form, Modal, Segmented, UploadFile } from 'antd';
 import { SegmentedValue } from 'antd/es/segmented';
+import camelCase from 'lodash/camelCase';
 import omit from 'lodash/omit';
 import { useEffect, useRef, useState } from 'react';
 import { variableEnabledFieldMap } from '../constants';
@@ -17,20 +18,9 @@ import { useFetchModelId } from './hooks';
 import ModelSetting from './model-setting';
 import PromptEngine from './prompt-engine';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import styles from './index.less';
 
-enum ConfigurationSegmented {
-  AssistantSetting = 'Assistant Setting',
-  PromptEngine = 'Prompt Engine',
-  ModelSetting = 'Model Setting',
-}
-
-const segmentedMap = {
-  [ConfigurationSegmented.AssistantSetting]: AssistantSetting,
-  [ConfigurationSegmented.ModelSetting]: ModelSetting,
-  [ConfigurationSegmented.PromptEngine]: PromptEngine,
-};
-
 const layout = {
   labelCol: { span: 7 },
   wrapperCol: { span: 17 },
@@ -47,6 +37,18 @@ const validateMessages = {
   },
 };
 
+enum ConfigurationSegmented {
+  AssistantSetting = 'Assistant Setting',
+  PromptEngine = 'Prompt Engine',
+  ModelSetting = 'Model Setting',
+}
+
+const segmentedMap = {
+  [ConfigurationSegmented.AssistantSetting]: AssistantSetting,
+  [ConfigurationSegmented.ModelSetting]: ModelSetting,
+  [ConfigurationSegmented.PromptEngine]: PromptEngine,
+};
+
 interface IProps extends IModalManagerChildrenProps {
   initialDialog: IDialog;
   loading: boolean;
@@ -63,11 +65,13 @@ const ChatConfigurationModal = ({
   clearDialog,
 }: IProps) => {
   const [form] = Form.useForm();
+
   const [value, setValue] = useState<ConfigurationSegmented>(
     ConfigurationSegmented.AssistantSetting,
   );
   const promptEngineRef = useRef<Array<IPromptConfigParameters>>([]);
   const modelId = useFetchModelId(visible);
+  const { t } = useTranslate('chat');
 
   const handleOk = async () => {
     const values = await form.validateFields();
@@ -115,10 +119,9 @@ const ChatConfigurationModal = ({
     <Flex gap={16}>
       <ChatConfigurationAtom></ChatConfigurationAtom>
       <div>
-        <b>Chat Configuration</b>
+        <b>{t('chatConfiguration')}</b>
         <div className={styles.chatConfigurationDescription}>
-          Here, dress up a dedicated assistant for your special knowledge bases!
-          đź’•
+          {t('chatConfigurationDescription')}
         </div>
       </div>
     </Flex>
@@ -158,7 +161,10 @@ const ChatConfigurationModal = ({
         size={'large'}
         value={value}
         onChange={handleSegmentedChange}
-        options={Object.values(ConfigurationSegmented)}
+        options={Object.values(ConfigurationSegmented).map((x) => ({
+          label: t(camelCase(x)),
+          value: x,
+        }))}
         block
       />
       <Divider></Divider>
diff --git a/web/src/pages/chat/chat-configuration-modal/model-setting.tsx b/web/src/pages/chat/chat-configuration-modal/model-setting.tsx
index 87390ab2b625ab463ee180a1b8ebf4cfa861d188..6f2ec7745d02da68eef54707f2d61b006d621241 100644
--- a/web/src/pages/chat/chat-configuration-modal/model-setting.tsx
+++ b/web/src/pages/chat/chat-configuration-modal/model-setting.tsx
@@ -5,16 +5,19 @@ import {
 } from '@/constants/knowledge';
 import { Divider, Flex, Form, InputNumber, Select, Slider, Switch } from 'antd';
 import classNames from 'classnames';
+import camelCase from 'lodash/camelCase';
 import { useEffect } from 'react';
 import { ISegmentedContentProps } from '../interface';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import { useFetchLlmList, useSelectLlmOptions } from '@/hooks/llmHooks';
 import { variableEnabledFieldMap } from '../constants';
 import styles from './index.less';
 
 const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
+  const { t } = useTranslate('chat');
   const parameterOptions = Object.values(ModelVariableType).map((x) => ({
-    label: x,
+    label: t(camelCase(x)),
     value: x,
   }));
 
@@ -44,18 +47,18 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
       })}
     >
       <Form.Item
-        label="Model"
+        label={t('model')}
         name="llm_id"
-        tooltip="Large language chat model"
-        rules={[{ required: true, message: 'Please select!' }]}
+        tooltip={t('modelTip')}
+        rules={[{ required: true, message: t('modelMessage') }]}
       >
         <Select options={modelOptions} showSearch />
       </Form.Item>
       <Divider></Divider>
       <Form.Item
-        label="Freedom"
+        label={t('freedom')}
         name="parameters"
-        tooltip="'Precise' means the LLM will be conservative and answer your question cautiously. 'Improvise' means the you want LLM talk much and freely. 'Balance' is between cautiously and freely."
+        tooltip={t('freedomTip')}
         initialValue={ModelVariableType.Precise}
         // rules={[{ required: true, message: 'Please input!' }]}
       >
@@ -64,7 +67,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           onChange={handleParametersChange}
         />
       </Form.Item>
-      <Form.Item label="Temperature" tooltip={'This parameter controls the randomness of predictions by the model. A lower temperature makes the model more confident in its responses, while a higher temperature makes it more creative and diverse.'}>
+      <Form.Item label={t('temperature')} tooltip={t('temperatureTip')}>
         <Flex gap={20} align="center">
           <Form.Item
             name={'temperatureEnabled'}
@@ -77,7 +80,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
             <Form.Item
               name={['llm_setting', 'temperature']}
               noStyle
-              rules={[{ required: true, message: 'Temperature is required' }]}
+              rules={[{ required: true, message: t('temperatureMessage') }]}
             >
               <Slider className={styles.variableSlider} max={1} step={0.01} />
             </Form.Item>
@@ -85,7 +88,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           <Form.Item
             name={['llm_setting', 'temperature']}
             noStyle
-            rules={[{ required: true, message: 'Temperature is required' }]}
+            rules={[{ required: true, message: t('temperatureMessage') }]}
           >
             <InputNumber
               className={styles.sliderInputNumber}
@@ -96,7 +99,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           </Form.Item>
         </Flex>
       </Form.Item>
-      <Form.Item label="Top P" tooltip={'Also known as “nucleus sampling,” this parameter sets a threshold to select a smaller set of words to sample from. It focuses on the most likely words, cutting off the less probable ones.'}>
+      <Form.Item label={t('topP')} tooltip={t('topPTip')}>
         <Flex gap={20} align="center">
           <Form.Item name={'topPEnabled'} valuePropName="checked" noStyle>
             <Switch size="small" />
@@ -105,7 +108,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
             <Form.Item
               name={['llm_setting', 'top_p']}
               noStyle
-              rules={[{ required: true, message: 'Top_p is required' }]}
+              rules={[{ required: true, message: t('topPMessage') }]}
             >
               <Slider className={styles.variableSlider} max={1} step={0.01} />
             </Form.Item>
@@ -113,7 +116,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           <Form.Item
             name={['llm_setting', 'top_p']}
             noStyle
-            rules={[{ required: true, message: 'Top_p is required' }]}
+            rules={[{ required: true, message: t('topPMessage') }]}
           >
             <InputNumber
               className={styles.sliderInputNumber}
@@ -124,7 +127,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           </Form.Item>
         </Flex>
       </Form.Item>
-      <Form.Item label="Presence Penalty" tooltip={'This discourages the model from repeating the same information by penalizing words that have already appeared in the conversation.'}>
+      <Form.Item label={t('presencePenalty')} tooltip={t('presencePenaltyTip')}>
         <Flex gap={20} align="center">
           <Form.Item
             name={'presencePenaltyEnabled'}
@@ -137,9 +140,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
             <Form.Item
               name={['llm_setting', 'presence_penalty']}
               noStyle
-              rules={[
-                { required: true, message: 'Presence Penalty is required' },
-              ]}
+              rules={[{ required: true, message: t('presencePenaltyMessage') }]}
             >
               <Slider className={styles.variableSlider} max={1} step={0.01} />
             </Form.Item>
@@ -147,9 +148,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           <Form.Item
             name={['llm_setting', 'presence_penalty']}
             noStyle
-            rules={[
-              { required: true, message: 'Presence Penalty is required' },
-            ]}
+            rules={[{ required: true, message: t('presencePenaltyMessage') }]}
           >
             <InputNumber
               className={styles.sliderInputNumber}
@@ -160,7 +159,10 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           </Form.Item>
         </Flex>
       </Form.Item>
-      <Form.Item label="Frequency Penalty" tooltip={'Similar to the presence penalty, this reduces the model’s tendency to repeat the same words frequently.'}>
+      <Form.Item
+        label={t('frequencyPenalty')}
+        tooltip={t('frequencyPenaltyTip')}
+      >
         <Flex gap={20} align="center">
           <Form.Item
             name={'frequencyPenaltyEnabled'}
@@ -174,7 +176,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
               name={['llm_setting', 'frequency_penalty']}
               noStyle
               rules={[
-                { required: true, message: 'Frequency Penalty is required' },
+                { required: true, message: t('frequencyPenaltyMessage') },
               ]}
             >
               <Slider className={styles.variableSlider} max={1} step={0.01} />
@@ -183,9 +185,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           <Form.Item
             name={['llm_setting', 'frequency_penalty']}
             noStyle
-            rules={[
-              { required: true, message: 'Frequency Penalty is required' },
-            ]}
+            rules={[{ required: true, message: t('frequencyPenaltyMessage') }]}
           >
             <InputNumber
               className={styles.sliderInputNumber}
@@ -196,7 +196,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           </Form.Item>
         </Flex>
       </Form.Item>
-      <Form.Item label="Max Tokens" tooltip={'This sets the maximum length of the model’s output, measured in the number of tokens (words or pieces of words).'}>
+      <Form.Item label={t('maxTokens')} tooltip={t('maxTokensTip')}>
         <Flex gap={20} align="center">
           <Form.Item name={'maxTokensEnabled'} valuePropName="checked" noStyle>
             <Switch size="small" />
@@ -205,7 +205,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
             <Form.Item
               name={['llm_setting', 'max_tokens']}
               noStyle
-              rules={[{ required: true, message: 'Max Tokens is required' }]}
+              rules={[{ required: true, message: t('maxTokensMessage') }]}
             >
               <Slider className={styles.variableSlider} max={2048} />
             </Form.Item>
@@ -213,7 +213,7 @@ const ModelSetting = ({ show, form }: ISegmentedContentProps) => {
           <Form.Item
             name={['llm_setting', 'max_tokens']}
             noStyle
-            rules={[{ required: true, message: 'Max Tokens is required' }]}
+            rules={[{ required: true, message: t('maxTokensMessage') }]}
           >
             <InputNumber
               className={styles.sliderInputNumber}
diff --git a/web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx b/web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx
index 1fc6e1006facbad525a587c72cd92d2e2e182c80..1e49bc948572a454d40a10259ba3bebda94ecfa7 100644
--- a/web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx
+++ b/web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx
@@ -29,6 +29,7 @@ import {
 } from '../interface';
 import { EditableCell, EditableRow } from './editable-cell';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import { useSelectPromptConfigParameters } from '../hooks';
 import styles from './index.less';
 
@@ -44,6 +45,7 @@ const PromptEngine = (
 ) => {
   const [dataSource, setDataSource] = useState<DataType[]>([]);
   const parameters = useSelectPromptConfigParameters();
+  const { t } = useTranslate('chat');
 
   const components = {
     body: {
@@ -102,7 +104,7 @@ const PromptEngine = (
 
   const columns: TableProps<DataType>['columns'] = [
     {
-      title: 'key',
+      title: t('key'),
       dataIndex: 'variable',
       key: 'variable',
       onCell: (record: DataType) => ({
@@ -114,7 +116,7 @@ const PromptEngine = (
       }),
     },
     {
-      title: 'optional',
+      title: t('optional'),
       dataIndex: 'optional',
       key: 'optional',
       width: 40,
@@ -130,7 +132,7 @@ const PromptEngine = (
       },
     },
     {
-      title: 'operation',
+      title: t('operation'),
       dataIndex: 'operation',
       width: 30,
       key: 'operation',
@@ -152,24 +154,21 @@ const PromptEngine = (
       })}
     >
       <Form.Item
-        label="System"
-        rules={[{ required: true, message: 'Please input!' }]}
-        tooltip="Instructions you need LLM to follow when LLM answers questions, like charactor design, answer length and answer language etc."
+        label={t('system')}
+        rules={[{ required: true, message: t('systemMessage') }]}
+        tooltip={t('systemTip')}
         name={['prompt_config', 'system']}
-        initialValue={`你是一个智能助手,请总结知识库的内容来回答问题,请列举知识库中的数据详细回答。当所有知识库内容都与问题无关时,你的回答必须包括“知识库中未找到您要的答案!”这句话。回答需要考虑聊天历史。
-        以下是知识库:
-        {knowledge}
-        以上是知识库。`}
+        initialValue={t('systemInitialValue')}
       >
         <Input.TextArea autoSize={{ maxRows: 8, minRows: 5 }} />
       </Form.Item>
       <Divider></Divider>
       <SimilaritySlider isTooltipShown></SimilaritySlider>
       <Form.Item<FieldType>
-        label="Top N"
+        label={t('topN')}
         name={'top_n'}
         initialValue={8}
-        tooltip={`Not all the chunks whose similarity score is above the 'simialrity threashold' will be feed to LLMs. LLM can only see these 'Top N' chunks.`}
+        tooltip={t('topNTip')}
       >
         <Slider max={30} />
       </Form.Item>
@@ -177,18 +176,15 @@ const PromptEngine = (
         <Row align={'middle'} justify="end">
           <Col span={7} className={styles.variableAlign}>
             <label className={styles.variableLabel}>
-              Variables
-              <Tooltip title="If you use dialog APIs, the varialbes might help you chat with your clients with different strategies. 
-              The variables are used to fill-in the 'System' part in prompt in order to give LLM a hint.
-              The 'knowledge' is a very special variable which will be filled-in with the retrieved chunks.
-              All the variables in 'System' should be curly bracketed.">
+              {t('variable')}
+              <Tooltip title={t('variableTip')}>
                 <QuestionCircleOutlined className={styles.variableIcon} />
               </Tooltip>
             </label>
           </Col>
           <Col span={17} className={styles.variableAlign}>
             <Button size="small" onClick={handleAdd}>
-              Add
+              {t('add')}
             </Button>
           </Col>
         </Row>
diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx
index 887e92f5876b87aab07ccda1dd8cba4e72da49eb..128bbe69a8edcf322dcd833dd6f9d86e72ea2851 100644
--- a/web/src/pages/chat/chat-container/index.tsx
+++ b/web/src/pages/chat/chat-container/index.tsx
@@ -37,6 +37,7 @@ import {
 } from '../hooks';
 
 import SvgIcon from '@/components/svg-icon';
+import { useTranslate } from '@/hooks/commonHooks';
 import { getExtension, isPdf } from '@/utils/documentUtils';
 import styles from './index.less';
 
@@ -298,6 +299,7 @@ const ChatContainer = () => {
   const disabled = useGetSendButtonDisabled();
   useGetFileIcon();
   const loading = useSelectConversationLoading();
+  const { t } = useTranslate('chat');
 
   return (
     <>
@@ -328,7 +330,7 @@ const ChatContainer = () => {
         </Flex>
         <Input
           size="large"
-          placeholder="Message Resume Assistant..."
+          placeholder={t('sendPlaceholder')}
           value={value}
           disabled={disabled}
           suffix={
@@ -338,7 +340,7 @@ const ChatContainer = () => {
               loading={sendLoading}
               disabled={disabled}
             >
-              Send
+              {t('send')}
             </Button>
           }
           onPressEnter={handlePressEnter}
diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx
index 183914089b4aa79ace387e96018f610b87ee4261..ba18215e78d9d68d63af65eba74ab51c84d726e8 100644
--- a/web/src/pages/chat/index.tsx
+++ b/web/src/pages/chat/index.tsx
@@ -35,6 +35,7 @@ import {
   useSelectFirstDialogOnMount,
 } from './hooks';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import styles from './index.less';
 
 const Chat = () => {
@@ -71,6 +72,7 @@ const Chat = () => {
   } = useEditDialog();
   const dialogLoading = useSelectDialogListLoading();
   const conversationLoading = useSelectConversationListLoading();
+  const { t } = useTranslate('chat');
 
   useFetchDialogOnMount(dialogId, true);
 
@@ -132,7 +134,8 @@ const Chat = () => {
       onClick: handleCreateTemporaryConversation,
       label: (
         <Space>
-          <EditOutlined /> New chat
+          <EditOutlined />
+          {t('newChat')}
         </Space>
       ),
     },
@@ -146,7 +149,7 @@ const Chat = () => {
         label: (
           <Space>
             <EditOutlined />
-            Edit
+            {t('edit', { keyPrefix: 'common' })}
           </Space>
         ),
       },
@@ -157,7 +160,7 @@ const Chat = () => {
         label: (
           <Space>
             <DeleteOutlined />
-            Delete chat
+            {t('delete', { keyPrefix: 'common' })}
           </Space>
         ),
       },
@@ -250,7 +253,7 @@ const Chat = () => {
             className={styles.chatTitle}
           >
             <Space>
-              <b>Chat</b>
+              <b>{t('chat')}</b>
               <Tag>{conversationList.length}</Tag>
             </Space>
             <Dropdown menu={{ items }}>
diff --git a/web/src/pages/chat/model.ts b/web/src/pages/chat/model.ts
index 22bf7b48e8c874b86c4fd27b558699db7001f130..1e94be0917100f723b474d23e5b1b1ab41826c8b 100644
--- a/web/src/pages/chat/model.ts
+++ b/web/src/pages/chat/model.ts
@@ -1,4 +1,5 @@
 import { IConversation, IDialog, Message } from '@/interfaces/database/chat';
+import i18n from '@/locales/config';
 import chatService from '@/services/chatService';
 import { message } from 'antd';
 import { DvaModel } from 'umi';
@@ -77,7 +78,9 @@ const model: DvaModel<ChatModelState> = {
       const { data } = yield call(chatService.setDialog, payload);
       if (data.retcode === 0) {
         yield put({ type: 'listDialog' });
-        message.success(payload.dialog_id ? 'Modified!' : 'Created!');
+        message.success(
+          i18n.t(`message.${payload.dialog_id ? 'modified' : 'created'}`),
+        );
       }
       return data.retcode;
     },
@@ -85,7 +88,7 @@ const model: DvaModel<ChatModelState> = {
       const { data } = yield call(chatService.removeDialog, payload);
       if (data.retcode === 0) {
         yield put({ type: 'listDialog' });
-        message.success('Deleted successfully !');
+        message.success(i18n.t('message.deleted'));
       }
       return data.retcode;
     },
@@ -152,7 +155,7 @@ const model: DvaModel<ChatModelState> = {
           type: 'listConversation',
           payload: { dialog_id: payload.dialog_id },
         });
-        message.success('Deleted successfully !');
+        message.success(i18n.t('message.deleted'));
       }
       return data.retcode;
     },
diff --git a/web/src/pages/login/index.tsx b/web/src/pages/login/index.tsx
index 1de7e933bbed40d0124f8d08fb39b91f9bea1bef..98700dc9afc6d633aefcb023640aeaa3c7239340 100644
--- a/web/src/pages/login/index.tsx
+++ b/web/src/pages/login/index.tsx
@@ -75,7 +75,7 @@ const Login = () => {
       <div className={styles.loginLeft}>
         <div className={styles.leftContainer}>
           <div className={styles.loginTitle}>
-            <div>{title === 'login' ? t('login') : 'Create an account'}</div>
+            <div>{title === 'login' ? t('login') : t('register')}</div>
             <span>
               {title === 'login'
                 ? t('loginDescription')
diff --git a/web/src/pages/login/model.ts b/web/src/pages/login/model.ts
index eaa92fb265031baf79e7dfb04bcb8add803bbafb..38865b190059d5f9c31c3d0d878c6753e8533136 100644
--- a/web/src/pages/login/model.ts
+++ b/web/src/pages/login/model.ts
@@ -1,4 +1,5 @@
 import { Authorization } from '@/constants/authorization';
+import i18n from '@/locales/config';
 import userService from '@/services/userService';
 import authorizationUtil from '@/utils/authorizationUtil';
 import { message } from 'antd';
@@ -31,7 +32,7 @@ const model: DvaModel<LoginModelState> = {
       const { retcode, data: res } = data;
       const authorization = response.headers.get(Authorization);
       if (retcode === 0) {
-        message.success('logged!');
+        message.success(i18n.t('message.logged'));
         const token = res.access_token;
         const userInfo = {
           avatar: res.avatar,
@@ -51,7 +52,7 @@ const model: DvaModel<LoginModelState> = {
       console.log();
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Registered!');
+        message.success(i18n.t('message.registered'));
       }
       return retcode;
     },
@@ -59,7 +60,7 @@ const model: DvaModel<LoginModelState> = {
       const { data } = yield call(userService.logout, payload);
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('logout');
+        message.success(i18n.t('message.logout'));
       }
       return retcode;
     },
diff --git a/web/src/pages/login/right-panel.tsx b/web/src/pages/login/right-panel.tsx
index f4072567039fba4e307c739cae21b78c59d0ab58..964351325cadb13944627eba2528b6b9efeeaf30 100644
--- a/web/src/pages/login/right-panel.tsx
+++ b/web/src/pages/login/right-panel.tsx
@@ -3,11 +3,13 @@ import SvgIcon from '@/components/svg-icon';
 import { Flex, Rate, Space, Typography } from 'antd';
 import classNames from 'classnames';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import styles from './index.less';
 
 const { Title, Text } = Typography;
 
 const LoginRightPanel = () => {
+  const { t } = useTranslate('login');
   return (
     <section className={styles.rightPanel}>
       <SvgIcon name="login-star" width={80}></SvgIcon>
@@ -16,11 +18,10 @@ const LoginRightPanel = () => {
           level={1}
           className={classNames(styles.white, styles.loginTitle)}
         >
-          Start building your smart assisstants.
+          {t('title')}
         </Title>
         <Text className={classNames(styles.pink, styles.loginDescription)}>
-          Sign up for free to explore top RAG technology. Create knowledge bases
-          and AIs to empower your business.
+          {t('description')}
         </Text>
         <Flex align="center" gap={16}>
           <Avatars></Avatars>
@@ -34,7 +35,7 @@ const LoginRightPanel = () => {
               </span>
             </Space>
             <span className={classNames(styles.pink, styles.loginRateReviews)}>
-              from 500+ reviews
+              {t('review')}
             </span>
           </Flex>
         </Flex>
diff --git a/web/src/pages/user-setting/components/setting-title/index.tsx b/web/src/pages/user-setting/components/setting-title/index.tsx
index 8ad153f3ad9e12f1c75ab7d77f0b157f42a29960..f5f8a7954c7c1c5759312d0fb673ac713b18c783 100644
--- a/web/src/pages/user-setting/components/setting-title/index.tsx
+++ b/web/src/pages/user-setting/components/setting-title/index.tsx
@@ -1,3 +1,4 @@
+import { useTranslate } from '@/hooks/commonHooks';
 import { SettingOutlined } from '@ant-design/icons';
 import { Button, Flex, Typography } from 'antd';
 
@@ -16,6 +17,8 @@ const SettingTitle = ({
   clickButton,
   showRightButton = false,
 }: IProps) => {
+  const { t } = useTranslate('setting');
+
   return (
     <Flex align="center" justify={'space-between'}>
       <div>
@@ -24,7 +27,7 @@ const SettingTitle = ({
       </div>
       {showRightButton && (
         <Button type={'primary'} onClick={clickButton}>
-          <SettingOutlined></SettingOutlined> System Model Settings
+          <SettingOutlined></SettingOutlined> {t('systemModelSettings')}
         </Button>
       )}
     </Flex>
diff --git a/web/src/pages/user-setting/model.ts b/web/src/pages/user-setting/model.ts
index 0caa12f33e2b9365514f53bd1a3656115f5f112b..5fffd8f4cf7057e7da6517fe3ef58f66ed7fbb3c 100644
--- a/web/src/pages/user-setting/model.ts
+++ b/web/src/pages/user-setting/model.ts
@@ -5,6 +5,7 @@ import {
   IThirdOAIModelCollection as IThirdAiModelCollection,
 } from '@/interfaces/database/llm';
 import { IUserInfo } from '@/interfaces/database/userSetting';
+import i18n from '@/locales/config';
 import userService from '@/services/userService';
 import { message } from 'antd';
 import { DvaModel } from 'umi';
@@ -47,7 +48,8 @@ const model: DvaModel<SettingModelState> = {
       const { data } = yield call(userService.setting, payload);
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Modified!');
+        message.success(i18n.t('message.modified'));
+
         yield put({
           type: 'getUserInfo',
         });
@@ -89,7 +91,8 @@ const model: DvaModel<SettingModelState> = {
       const { data } = yield call(userService.set_tenant_info, payload);
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Modified!');
+        message.success(i18n.t('message.modified'));
+
         yield put({
           type: 'getTenantInfo',
         });
@@ -137,7 +140,8 @@ const model: DvaModel<SettingModelState> = {
       const { data } = yield call(userService.set_api_key, payload);
       const { retcode } = data;
       if (retcode === 0) {
-        message.success('Modified!');
+        message.success(i18n.t('message.modified'));
+
         yield put({ type: 'my_llm' });
         yield put({ type: 'factories_list' });
         yield put({
diff --git a/web/src/pages/user-setting/setting-model/api-key-modal/index.tsx b/web/src/pages/user-setting/setting-model/api-key-modal/index.tsx
index e4270e423d9c4fe35e56d916a49e927204ab94d9..7a4850797168d7a668b60f4414be141124c9e14d 100644
--- a/web/src/pages/user-setting/setting-model/api-key-modal/index.tsx
+++ b/web/src/pages/user-setting/setting-model/api-key-modal/index.tsx
@@ -1,4 +1,5 @@
 import { IModalManagerChildrenProps } from '@/components/modal-manager';
+import { useTranslate } from '@/hooks/commonHooks';
 import { Form, Input, Modal } from 'antd';
 import { useEffect } from 'react';
 
@@ -24,6 +25,7 @@ const ApiKeyModal = ({
   onOk,
 }: IProps) => {
   const [form] = Form.useForm();
+  const { t } = useTranslate('setting');
 
   const handleOk = async () => {
     const ret = await form.validateFields();
@@ -49,7 +51,7 @@ const ApiKeyModal = ({
 
   return (
     <Modal
-      title="Modify"
+      title={t('modify')}
       open={visible}
       onOk={handleOk}
       onCancel={handleCancel}
@@ -67,18 +69,18 @@ const ApiKeyModal = ({
         form={form}
       >
         <Form.Item<FieldType>
-          label="Api-Key"
+          label={t('apiKey')}
           name="api_key"
-          tooltip="The API key can be obtained by registering the corresponding LLM supplier."
-          rules={[{ required: true, message: 'Please input api key!' }]}
+          tooltip={t('apiKeyTip')}
+          rules={[{ required: true, message: t('apiKeyMessage') }]}
         >
           <Input />
         </Form.Item>
         {llmFactory === 'OpenAI' && (
           <Form.Item<FieldType>
-            label="Base-Url"
+            label={t('baseUrl')}
             name="base_url"
-            tooltip="If your API key is from OpenAI, just ignore it. Any other intermediate providers will give this base url with the API key."
+            tooltip={t('baseUrlTip')}
           >
             <Input placeholder="https://api.openai.com/v1" />
           </Form.Item>
diff --git a/web/src/pages/user-setting/setting-model/index.tsx b/web/src/pages/user-setting/setting-model/index.tsx
index 4c8d2e8fe60005595cde799d0803b96e503b9bf7..03dd050d7461444edf57ec414beaa45db5c38335 100644
--- a/web/src/pages/user-setting/setting-model/index.tsx
+++ b/web/src/pages/user-setting/setting-model/index.tsx
@@ -1,5 +1,5 @@
 import { ReactComponent as MoreModelIcon } from '@/assets/svg/more-model.svg';
-import { useSetModalState } from '@/hooks/commonHooks';
+import { useSetModalState, useTranslate } from '@/hooks/commonHooks';
 import {
   LlmItem,
   useFetchLlmFactoryListOnMount,
@@ -64,6 +64,7 @@ interface IModelCardProps {
 
 const ModelCard = ({ item, clickApiKey }: IModelCardProps) => {
   const { visible, switchVisible } = useSetModalState();
+  const { t } = useTranslate('setting');
 
   const handleApiKeyClick = () => {
     clickApiKey(item.name);
@@ -94,7 +95,7 @@ const ModelCard = ({ item, clickApiKey }: IModelCardProps) => {
               </Button>
               <Button onClick={handleShowMoreClick}>
                 <Flex gap={'small'}>
-                  Show more models
+                  {t('showMoreModels')}
                   <MoreModelIcon />
                 </Flex>
               </Button>
@@ -140,6 +141,7 @@ const UserSettingModel = () => {
     hideSystemSettingModal,
     showSystemSettingModal,
   } = useSubmitSystemModelSetting();
+  const { t } = useTranslate('setting');
 
   const handleApiKeyClick = useCallback(
     (llmFactory: string) => {
@@ -155,7 +157,7 @@ const UserSettingModel = () => {
   const items: CollapseProps['items'] = [
     {
       key: '1',
-      label: 'Added models',
+      label: t('addedModels'),
       children: (
         <List
           grid={{ gutter: 16, column: 1 }}
@@ -168,7 +170,7 @@ const UserSettingModel = () => {
     },
     {
       key: '2',
-      label: 'Models to be added',
+      label: t('modelsToBeAdded'),
       children: (
         <List
           grid={{
@@ -193,7 +195,7 @@ const UserSettingModel = () => {
                 </Flex>
                 <Divider></Divider>
                 <Button type="link" onClick={handleAddModel(item.name)}>
-                  Add the model
+                  {t('addTheModel')}
                 </Button>
               </Card>
             </List.Item>
@@ -208,8 +210,8 @@ const UserSettingModel = () => {
       <Spin spinning={loading}>
         <section className={styles.modelWrapper}>
           <SettingTitle
-            title="Model Setting"
-            description="Manage your account settings and preferences here."
+            title={t('model')}
+            description={t('profileDescription')}
             showRightButton
             clickButton={showSystemSettingModal}
           ></SettingTitle>
diff --git a/web/src/pages/user-setting/setting-model/system-model-setting-modal/index.tsx b/web/src/pages/user-setting/setting-model/system-model-setting-modal/index.tsx
index 1deb482e64f5fbefb56f80521c68c746028d8a3b..53ee20631e02d63037b13b5b8db26e4bd50f0ace 100644
--- a/web/src/pages/user-setting/setting-model/system-model-setting-modal/index.tsx
+++ b/web/src/pages/user-setting/setting-model/system-model-setting-modal/index.tsx
@@ -1,5 +1,6 @@
 import { IModalManagerChildrenProps } from '@/components/modal-manager';
 import { LlmModelType } from '@/constants/knowledge';
+import { useTranslate } from '@/hooks/commonHooks';
 import { ISystemModelSettingSavingParams } from '@/hooks/llmHooks';
 import { Form, Modal, Select } from 'antd';
 import { useEffect } from 'react';
@@ -21,6 +22,7 @@ const SystemModelSettingModal = ({
   const [form] = Form.useForm();
   const { systemSetting: initialValues, allOptions } =
     useFetchSystemModelSettingOnMount(visible);
+  const { t } = useTranslate('setting');
 
   const handleOk = async () => {
     const values = await form.validateFields();
@@ -35,7 +37,7 @@ const SystemModelSettingModal = ({
 
   return (
     <Modal
-      title="System Model Settings"
+      title={t('systemModelSettings')}
       open={visible}
       onOk={handleOk}
       onCancel={hideModal}
@@ -43,25 +45,32 @@ const SystemModelSettingModal = ({
       confirmLoading={loading}
     >
       <Form form={form} onValuesChange={onFormLayoutChange} layout={'vertical'}>
-        
-      <Form.Item label="Chat model" name="llm_id" tooltip="The default chat LLM all the newly created knowledgebase will use.">
+        <Form.Item
+          label={t('chatModel')}
+          name="llm_id"
+          tooltip={t('chatModelTip')}
+        >
           <Select options={allOptions[LlmModelType.Chat]} />
         </Form.Item>
-        <Form.Item label="Embedding model" name="embd_id" tooltip="The default embedding model all the newly created knowledgebase will use.">
+        <Form.Item
+          label={t('embeddingModel')}
+          name="embd_id"
+          tooltip={t('embeddingModelTip')}
+        >
           <Select options={allOptions[LlmModelType.Embedding]} />
         </Form.Item>
         <Form.Item
-          label="Img2txt model"
+          label={t('img2txtModel')}
           name="img2txt_id"
-          tooltip="The default multi-module model all the newly created knowledgebase will use. It can describe a picture or video."
+          tooltip={t('img2txtModelTip')}
         >
           <Select options={allOptions[LlmModelType.Image2text]} />
         </Form.Item>
-        
+
         <Form.Item
-          label="Sequence2txt model"
+          label={t('sequence2txtModel')}
           name="asr_id"
-          tooltip="The default ASR model all the newly created knowledgebase will use. Use this model to translate voices to corresponding text."
+          tooltip={t('sequence2txtModelTip')}
         >
           <Select options={allOptions[LlmModelType.Speech2text]} />
         </Form.Item>
diff --git a/web/src/pages/user-setting/setting-password/index.tsx b/web/src/pages/user-setting/setting-password/index.tsx
index 919af726bd068b407a8aad48949fd1888dc75406..66e744ab1a09fa05bd3fa3c267de79a06d404272 100644
--- a/web/src/pages/user-setting/setting-password/index.tsx
+++ b/web/src/pages/user-setting/setting-password/index.tsx
@@ -5,6 +5,7 @@ import { Button, Divider, Form, Input, Space } from 'antd';
 import SettingTitle from '../components/setting-title';
 import { useValidateSubmittable } from '../hooks';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import parentStyles from '../index.less';
 import styles from './index.less';
 
@@ -22,6 +23,7 @@ const UserSettingPassword = () => {
   const loading = useOneNamespaceEffectsLoading('settingModel', ['setting']);
   const { form, submittable } = useValidateSubmittable();
   const saveSetting = useSaveSetting();
+  const { t } = useTranslate('setting');
 
   const onFinish = (values: any) => {
     const password = rsaPsw(values.password) as string;
@@ -37,8 +39,8 @@ const UserSettingPassword = () => {
   return (
     <section className={styles.passwordWrapper}>
       <SettingTitle
-        title="Password"
-        description="Please enter your current password to change your password."
+        title={t('password')}
+        description={t('passwordDescription')}
       ></SettingTitle>
       <Divider />
       <Form
@@ -56,12 +58,12 @@ const UserSettingPassword = () => {
         // requiredMark={'optional'}
       >
         <Form.Item<FieldType>
-          label="Current password"
+          label={t('currentPassword')}
           name="password"
           rules={[
             {
               required: true,
-              message: 'Please input your password!',
+              message: t('currentPasswordMessage'),
               whitespace: true,
             },
           ]}
@@ -69,14 +71,14 @@ const UserSettingPassword = () => {
           <Input.Password />
         </Form.Item>
         <Divider />
-        <Form.Item label="New password" required>
+        <Form.Item label={t('newPassword')} required>
           <Form.Item<FieldType>
             noStyle
             name="new_password"
             rules={[
               {
                 required: true,
-                message: 'Please input your password!',
+                message: t('newPasswordMessage'),
                 whitespace: true,
               },
             ]}
@@ -84,18 +86,18 @@ const UserSettingPassword = () => {
             <Input.Password />
           </Form.Item>
           <p className={parentStyles.itemDescription}>
-            Your new password must be more than 8 characters.
+            {t('newPasswordDescription')}
           </p>
         </Form.Item>
         <Divider />
         <Form.Item<FieldType>
-          label="Confirm new password"
+          label={t('confirmPassword')}
           name="confirm_password"
           dependencies={['new_password']}
           rules={[
             {
               required: true,
-              message: 'Please confirm your password!',
+              message: t('confirmPasswordMessage'),
               whitespace: true,
             },
             ({ getFieldValue }) => ({
@@ -104,7 +106,7 @@ const UserSettingPassword = () => {
                   return Promise.resolve();
                 }
                 return Promise.reject(
-                  new Error('The new password that you entered do not match!'),
+                  new Error(t('confirmPasswordNonMatchMessage')),
                 );
               },
             }),
@@ -120,14 +122,14 @@ const UserSettingPassword = () => {
           }
         >
           <Space>
-            <Button htmlType="button">Cancel</Button>
+            <Button htmlType="button">{t('cancel')}</Button>
             <Button
               type="primary"
               htmlType="submit"
               disabled={!submittable}
               loading={loading}
             >
-              Save
+              {t('save', { keyPrefix: 'common' })}
             </Button>
           </Space>
         </Form.Item>
diff --git a/web/src/pages/user-setting/setting-profile/index.tsx b/web/src/pages/user-setting/setting-profile/index.tsx
index 952dc7b16c864fbf20edb7518799de3cb46c5350..627af9379db3949e511a9ba8ede70f1ac2c0c177 100644
--- a/web/src/pages/user-setting/setting-profile/index.tsx
+++ b/web/src/pages/user-setting/setting-profile/index.tsx
@@ -29,6 +29,8 @@ import {
   useValidateSubmittable,
 } from '../hooks';
 
+import { useTranslate } from '@/hooks/commonHooks';
+import { useChangeLanguage } from '@/hooks/logicHooks';
 import parentStyles from '../index.less';
 import styles from './index.less';
 
@@ -54,6 +56,8 @@ const UserSettingProfile = () => {
   const { form, submittable } = useValidateSubmittable();
   const loading = useSelectUserInfoLoading();
   useFetchUserInfo();
+  const { t } = useTranslate('setting');
+  const changeLanguage = useChangeLanguage();
 
   const onFinish = async (values: any) => {
     const avatar = await getBase64FromUploadFileList(values.avatar);
@@ -72,8 +76,8 @@ const UserSettingProfile = () => {
   return (
     <section className={styles.profileWrapper}>
       <SettingTitle
-        title="Profile"
-        description="Update your photo and personal details here."
+        title={t('profile')}
+        description={t('profileDescription')}
       ></SettingTitle>
       <Divider />
       <Spin spinning={loading}>
@@ -91,12 +95,12 @@ const UserSettingProfile = () => {
           autoComplete="off"
         >
           <Form.Item<FieldType>
-            label="Username"
+            label={t('username')}
             name="nickname"
             rules={[
               {
                 required: true,
-                message: 'Please input your username!',
+                message: t('usernameMessage'),
                 whitespace: true,
               },
             ]}
@@ -107,8 +111,8 @@ const UserSettingProfile = () => {
           <Form.Item<FieldType>
             label={
               <div>
-                <Space>Your photo</Space>
-                <div>This will be displayed on your profile.</div>
+                <Space>{t('photo')}</Space>
+                <div>{t('photoDescription')}</div>
               </div>
             }
             name="avatar"
@@ -126,41 +130,53 @@ const UserSettingProfile = () => {
             >
               <button style={{ border: 0, background: 'none' }} type="button">
                 <PlusOutlined />
-                <div style={{ marginTop: 8 }}>Upload</div>
+                <div style={{ marginTop: 8 }}>
+                  {t('upload', { keyPrefix: 'common' })}
+                </div>
               </button>
             </Upload>
           </Form.Item>
           <Divider />
           <Form.Item<FieldType>
-            label="Color schema"
+            label={t('colorSchema')}
             name="color_schema"
-            rules={[
-              { required: true, message: 'Please select your color schema!' },
-            ]}
+            rules={[{ required: true, message: t('colorSchemaMessage') }]}
           >
-            <Select placeholder="select your color schema">
-              <Option value="Bright">Bright</Option>
-              <Option value="Dark">Dark</Option>
+            <Select placeholder={t('colorSchemaPlaceholder')}>
+              <Option value="Bright">{t('bright')}</Option>
+              <Option value="Dark">{t('dark')}</Option>
             </Select>
           </Form.Item>
           <Divider />
           <Form.Item<FieldType>
-            label="Language"
+            label={t('language', { keyPrefix: 'common' })}
             name="language"
-            rules={[{ required: true, message: 'Please input your language!' }]}
+            rules={[
+              {
+                required: true,
+                message: t('languageMessage', { keyPrefix: 'common' }),
+              },
+            ]}
           >
-            <Select placeholder="select your language">
-              <Option value="English">English</Option>
-              <Option value="Chinese">Chinese</Option>
+            <Select
+              placeholder={t('languagePlaceholder', { keyPrefix: 'common' })}
+              onChange={changeLanguage}
+            >
+              <Option value="English">
+                {t('english', { keyPrefix: 'common' })}
+              </Option>
+              <Option value="Chinese">
+                {t('chinese', { keyPrefix: 'common' })}
+              </Option>
             </Select>
           </Form.Item>
           <Divider />
           <Form.Item<FieldType>
-            label="Timezone"
+            label={t('timezone')}
             name="timezone"
-            rules={[{ required: true, message: 'Please input your timezone!' }]}
+            rules={[{ required: true, message: t('timezoneMessage') }]}
           >
-            <Select placeholder="select your timezone" showSearch>
+            <Select placeholder={t('timezonePlaceholder')} showSearch>
               {TimezoneList.map((x) => (
                 <Option value={x} key={x}>
                   {x}
@@ -169,12 +185,12 @@ const UserSettingProfile = () => {
             </Select>
           </Form.Item>
           <Divider />
-          <Form.Item label="Email address">
+          <Form.Item label={t('email')}>
             <Form.Item<FieldType> name="email" noStyle>
               <Input disabled />
             </Form.Item>
             <p className={parentStyles.itemDescription}>
-              Once registered, E-mail cannot be changed.
+              {t('emailDescription')}
             </p>
           </Form.Item>
           <Form.Item
@@ -184,14 +200,14 @@ const UserSettingProfile = () => {
             }
           >
             <Space>
-              <Button htmlType="button">Cancel</Button>
+              <Button htmlType="button">{t('cancel')}</Button>
               <Button
                 type="primary"
                 htmlType="submit"
                 disabled={!submittable}
                 loading={submitLoading}
               >
-                Save
+                {t('save', { keyPrefix: 'common' })}
               </Button>
             </Space>
           </Form.Item>
diff --git a/web/src/pages/user-setting/setting-team/index.tsx b/web/src/pages/user-setting/setting-team/index.tsx
index 48dab39e991eccb179fb785469b646dbb2b18161..c2445f038353a76f58632332e11a8588df779620 100644
--- a/web/src/pages/user-setting/setting-team/index.tsx
+++ b/web/src/pages/user-setting/setting-team/index.tsx
@@ -1,17 +1,21 @@
 import { Button, Card, Flex } from 'antd';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import { useSelectUserInfo } from '@/hooks/userSettingHook';
 import styles from './index.less';
 
 const UserSettingTeam = () => {
   const userInfo = useSelectUserInfo();
+  const { t } = useTranslate('setting');
 
   return (
     <div className={styles.teamWrapper}>
       <Card className={styles.teamCard}>
         <Flex align="center" justify={'space-between'}>
-          <span>{userInfo.nickname} Workspace</span>
-          <Button type="primary">Upgrade</Button>
+          <span>
+            {userInfo.nickname} {t('workspace')}
+          </span>
+          <Button type="primary">{t('upgrade')}</Button>
         </Flex>
       </Card>
     </div>
diff --git a/web/src/pages/user-setting/sidebar/index.tsx b/web/src/pages/user-setting/sidebar/index.tsx
index 097ab5f6465b590de52165074deeb0be69e8a68e..0945e31e11634f607b794b790322ce7f86d04bc1 100644
--- a/web/src/pages/user-setting/sidebar/index.tsx
+++ b/web/src/pages/user-setting/sidebar/index.tsx
@@ -7,38 +7,39 @@ import {
   UserSettingBaseKey,
   UserSettingIconMap,
   UserSettingRouteKey,
-  UserSettingRouteMap,
 } from '../constants';
 
+import { useTranslate } from '@/hooks/commonHooks';
 import { useLogout } from '@/hooks/userSettingHook';
 import styles from './index.less';
 
 type MenuItem = Required<MenuProps>['items'][number];
 
-function getItem(
-  label: React.ReactNode,
-  key: React.Key,
-  icon?: React.ReactNode,
-  children?: MenuItem[],
-  type?: 'group',
-): MenuItem {
-  return {
-    key,
-    icon,
-    children,
-    label,
-    type,
-  } as MenuItem;
-}
-
-const items: MenuItem[] = Object.values(UserSettingRouteKey).map((value) =>
-  getItem(UserSettingRouteMap[value], value, UserSettingIconMap[value]),
-);
-
 const SideBar = () => {
   const navigate = useNavigate();
   const pathName = useSecondPathName();
   const logout = useLogout();
+  const { t } = useTranslate('setting');
+
+  function getItem(
+    label: string,
+    key: React.Key,
+    icon?: React.ReactNode,
+    children?: MenuItem[],
+    type?: 'group',
+  ): MenuItem {
+    return {
+      key,
+      icon,
+      children,
+      label: t(label),
+      type,
+    } as MenuItem;
+  }
+
+  const items: MenuItem[] = Object.values(UserSettingRouteKey).map((value) =>
+    getItem(value, value, UserSettingIconMap[value]),
+  );
 
   const handleMenuClick: MenuProps['onClick'] = ({ key }) => {
     if (key === UserSettingRouteKey.Logout) {
diff --git a/web/src/utils/authorizationUtil.ts b/web/src/utils/authorizationUtil.ts
index a2b3d06908e6906cd6951d4e993f32503a807733..f4b8b5e7e1bad766e9658e714bca48ceba7180f5 100644
--- a/web/src/utils/authorizationUtil.ts
+++ b/web/src/utils/authorizationUtil.ts
@@ -38,6 +38,12 @@ const storage = {
       localStorage.removeItem(x);
     });
   },
+  setLanguage: (lng: string) => {
+    localStorage.setItem('lng', lng);
+  },
+  getLanguage: (): string => {
+    return localStorage.getItem('lng') as string;
+  },
 };
 
 export default storage;
diff --git a/web/src/utils/request.ts b/web/src/utils/request.ts
index adc77c572c35b19d661b42bfc3f84cbe3edd2525..c5fd867d122aae703612b73dcea946c6ee738963 100644
--- a/web/src/utils/request.ts
+++ b/web/src/utils/request.ts
@@ -1,4 +1,5 @@
 import { Authorization } from '@/constants/authorization';
+import i18n from '@/locales/config';
 import authorizationUtil from '@/utils/authorizationUtil';
 import { message, notification } from 'antd';
 import { history } from 'umi';
@@ -7,21 +8,21 @@ import { RequestMethod, extend } from 'umi-request';
 const ABORT_REQUEST_ERR_MESSAGE = 'The user aborted a request.'; // 手动中断请求。errorHandler 抛出的error message
 
 const RetcodeMessage = {
-  200: '服务器成功返回请求的数据。',
-  201: '新建或修改数据成功。',
-  202: '一个请求已经进入后台排队(异步任务)。',
-  204: '删除数据成功。',
-  400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
-  401: '用户没有权限(令牌、用户名、密码错误)。',
-  403: '用户得到授权,但是访问是被禁止的。',
-  404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
-  406: '请求的格式不可得。',
-  410: '请求的资源被永久删除,且不会再得到的。',
-  422: '当创建一个对象时,发生一个验证错误。',
-  500: '服务器发生错误,请检查服务器。',
-  502: '网关错误。',
-  503: '服务不可用,服务器暂时过载或维护。',
-  504: '网关超时。',
+  200: i18n.t('message.200'),
+  201: i18n.t('message.201'),
+  202: i18n.t('message.202'),
+  204: i18n.t('message.204'),
+  400: i18n.t('message.400'),
+  401: i18n.t('message.401'),
+  403: i18n.t('message.403'),
+  404: i18n.t('message.404'),
+  406: i18n.t('message.406'),
+  410: i18n.t('message.410'),
+  422: i18n.t('message.422'),
+  500: i18n.t('message.500'),
+  502: i18n.t('message.502'),
+  503: i18n.t('message.503'),
+  504: i18n.t('message.504'),
 };
 type ResultCode =
   | 200
@@ -62,13 +63,13 @@ const errorHandler = (error: {
         RetcodeMessage[response.status as ResultCode] || response.statusText;
       const { status, url } = response;
       notification.error({
-        message: `请求错误 ${status}: ${url}`,
+        message: `${i18n.t('message.requestError')} ${status}: ${url}`,
         description: errorText,
       });
     } else if (!response) {
       notification.error({
-        description: '您的网络发生异常,无法连接服务器',
-        message: '网络异常',
+        description: i18n.t('message.networkAnomalyDescription'),
+        message: i18n.t('message.networkAnomaly'),
       });
     }
   }
@@ -123,7 +124,7 @@ request.interceptors.response.use(async (response: any, options) => {
       message.error(data.retmsg);
     } else {
       notification.error({
-        message: `提示 : ${data.retcode}`,
+        message: `${i18n.t('message.hint')} : ${data.retcode}`,
         description: data.retmsg,
         duration: 3,
       });