From f173fe6e47cb5d1abb7baee1a7cf26a2c7bea5df Mon Sep 17 00:00:00 2001 From: balibabu <cike8899@users.noreply.github.com> Date: Fri, 12 Apr 2024 11:41:00 +0800 Subject: [PATCH] feat: Support Traditional Chinese (#336) ### What problem does this PR solve? Support Traditional Chinese Issue link: #335 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/app.tsx | 14 +- web/src/constants/common.ts | 8 + web/src/hooks/logicHooks.ts | 5 +- .../components/right-toolbar/index.tsx | 19 +- web/src/locales/config.ts | 3 + web/src/locales/en.ts | 3 +- web/src/locales/zh-traditional.ts | 419 ++++++++++++++++++ web/src/locales/zh.ts | 3 +- web/src/pages/user-setting/model.ts | 7 +- .../user-setting/setting-profile/index.tsx | 13 +- 10 files changed, 470 insertions(+), 24 deletions(-) create mode 100644 web/src/locales/zh-traditional.ts diff --git a/web/src/app.tsx b/web/src/app.tsx index f4aa150..e80c9b9 100644 --- a/web/src/app.tsx +++ b/web/src/app.tsx @@ -1,18 +1,26 @@ -import { default as i18n, default as i18next } from '@/locales/config'; +import i18n from '@/locales/config'; import { App, ConfigProvider, ConfigProviderProps } from 'antd'; import enUS from 'antd/locale/en_US'; import zhCN from 'antd/locale/zh_CN'; +import zh_HK from 'antd/locale/zh_HK'; import React, { ReactNode, useEffect, useState } from 'react'; import storage from './utils/authorizationUtil'; +const AntLanguageMap = { + en: enUS, + zh: zhCN, + 'zh-TRADITIONAL': zh_HK, +}; + type Locale = ConfigProviderProps['locale']; const RootProvider = ({ children }: React.PropsWithChildren) => { - const getLocale = (lng: string) => (lng === 'zh' ? zhCN : enUS); + const getLocale = (lng: string) => + AntLanguageMap[lng as keyof typeof AntLanguageMap] ?? enUS; const [locale, setLocal] = useState<Locale>(getLocale(storage.getLanguage())); - i18next.on('languageChanged', function (lng: string) { + i18n.on('languageChanged', function (lng: string) { storage.setLanguage(lng); setLocal(getLocale(lng)); }); diff --git a/web/src/constants/common.ts b/web/src/constants/common.ts index d315cf1..ea789e7 100644 --- a/web/src/constants/common.ts +++ b/web/src/constants/common.ts @@ -38,3 +38,11 @@ export const fileIconMap = { xlsx: 'xlsx.svg', xml: 'xml.svg', }; + +export const LanguageList = ['English', 'Chinese', 'Traditional Chinese']; + +export const LanguageTranslationMap = { + English: 'en', + Chinese: 'zh', + 'Traditional Chinese': 'zh-TRADITIONAL', +}; diff --git a/web/src/hooks/logicHooks.ts b/web/src/hooks/logicHooks.ts index 23833db..b1319dc 100644 --- a/web/src/hooks/logicHooks.ts +++ b/web/src/hooks/logicHooks.ts @@ -1,3 +1,4 @@ +import { LanguageTranslationMap } from '@/constants/common'; import { IKnowledgeFile } from '@/interfaces/database/knowledge'; import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; import { useCallback, useState } from 'react'; @@ -53,7 +54,9 @@ export const useChangeLanguage = () => { const saveSetting = useSaveSetting(); const changeLanguage = (lng: string) => { - i18n.changeLanguage(lng === 'Chinese' ? 'zh' : 'en'); + i18n.changeLanguage( + LanguageTranslationMap[lng as keyof typeof LanguageTranslationMap], + ); saveSetting({ language: lng }); }; diff --git a/web/src/layouts/components/right-toolbar/index.tsx b/web/src/layouts/components/right-toolbar/index.tsx index faca5c9..d60ec46 100644 --- a/web/src/layouts/components/right-toolbar/index.tsx +++ b/web/src/layouts/components/right-toolbar/index.tsx @@ -2,9 +2,11 @@ import { ReactComponent as TranslationIcon } from '@/assets/svg/translation.svg' import { useTranslate } from '@/hooks/commonHooks'; import { GithubOutlined } from '@ant-design/icons'; import { Dropdown, MenuProps, Space } from 'antd'; +import camelCase from 'lodash/camelCase'; import React from 'react'; import User from '../user'; +import { LanguageList } from '@/constants/common'; import { useChangeLanguage } from '@/hooks/logicHooks'; import styled from './index.less'; @@ -28,17 +30,12 @@ const RightToolBar = () => { changeLanguage(key); }; - const items: MenuProps['items'] = [ - { - key: 'English', - label: <span>{t('english')}</span>, - }, - { type: 'divider' }, - { - key: 'Chinese', - label: <span>{t('chinese')}</span>, - }, - ]; + const items: MenuProps['items'] = LanguageList.map((x) => ({ + key: x, + label: <span>{t(camelCase(x))}</span>, + })).reduce<MenuProps['items']>((pre, cur) => { + return [...pre!, { type: 'divider' }, cur]; + }, []); return ( <div className={styled.toolbarWrapper}> diff --git a/web/src/locales/config.ts b/web/src/locales/config.ts index 17b7a7f..782a1f7 100644 --- a/web/src/locales/config.ts +++ b/web/src/locales/config.ts @@ -3,15 +3,18 @@ import { initReactI18next } from 'react-i18next'; import translation_en from './en'; import translation_zh from './zh'; +import translation_zh_traditional from './zh-traditional'; const resources = { en: translation_en, zh: translation_zh, + 'zh-TRADITIONAL': translation_zh_traditional, }; i18n.use(initReactI18next).init({ resources, lng: 'en', + fallbackLng: 'en', interpolation: { escapeValue: false, }, diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 4a4ca55..1dccda9 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -15,7 +15,8 @@ export default { edit: 'Edit', upload: 'Upload', english: 'English', - chinese: 'Chinese', + chinese: 'Simplified Chinese', + traditionalChinese: 'Traditional Chinese', language: 'Language', languageMessage: 'Please input your language!', languagePlaceholder: 'select your language', diff --git a/web/src/locales/zh-traditional.ts b/web/src/locales/zh-traditional.ts new file mode 100644 index 0000000..b2a3e72 --- /dev/null +++ b/web/src/locales/zh-traditional.ts @@ -0,0 +1,419 @@ +export default { + translation: { + common: { + delete: 'ĺŞé™¤', + deleteModalTitle: '確定ĺŞé™¤ĺ—Ž?', + ok: 'ćŻ', + cancel: 'ĺ¦', + total: '總共', + rename: '重命ĺŤ', + name: 'ĺŤç¨±', + save: 'äżťćŚ', + namePlaceholder: '請輸入ĺŤç¨±', + next: '下一ćĄ', + create: '創建', + edit: '編輯', + upload: '上傳', + english: '英語', + chinese: 'ä¸ć–‡ç°ˇé«”', + traditionalChinese: 'ä¸ć–‡çąé«”', + 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: '啟用', + disabled: 'ç¦ç”¨', + 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: '上傳', + run: 'ĺ•źĺ‹•', + 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: '支ćŚĺ–®ć¬ˇć–批量上傳。嚴ç¦ä¸Šĺ‚łĺ…¬ĺŹ¸ć•¸ć“šć–其他é•ç¦ć–‡ä»¶ă€‚', + chunk: '解ćžĺˇŠ', + bulk: '批量', + cancel: '取ć¶', + }, + 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的粒度č‡'ć–‡ç« '一致,所有上層文本é˝ćśĺŚ…ĺ«ĺś¨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>“性ĺĄ/性ĺĄďĽç”·ć€§ďĽŚĺĄłć€§ďĽ‰â€ť</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: { + createAssistant: '新建助ç†', + assistantSetting: '助ç†č¨ç˝®', + promptEngine: 'ćŹç¤şĺĽ•ć“Ž', + modelSetting: '模型č¨ç˝®', + chat: 'čŠĺ¤©', + newChat: '新建čŠĺ¤©', + send: '發é€', + sendPlaceholder: 'ć¶ćŻć¦‚č¦ĺŠ©ć‰‹...', + chatConfiguration: 'čŠĺ¤©é…Ťç˝®', + chatConfigurationDescription: 'ĺś¨é€™čŁˇďĽŚç‚şä˝ çš„ĺ°ćĄçźĄč庫裝扮ĺ°ĺ±¬ĺŠ©ć‰‹ďĽđź’•', + assistantName: '助ç†ĺ§“ĺŤ', + assistantNameMessage: '助ç†ĺ§“ĺŤćŻĺż…ĺˇ«é …', + 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: 'é ‚ç´š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: 'sequence2Txt模型', + sequence2txtModelTip: + '所有新創建的知čĺş«é˝ĺ°‡ä˝żç”¨é»čŞŤçš„ ASR 模型。使用ć¤ć¨ˇĺž‹ĺ°‡čŞžéźłçż»čŻç‚şç›¸ć‡‰çš„文本。', + workspace: '工作空間', + upgrade: '升級', + addLlmTitle: 'ć·»ĺŠ Llm', + modelName: '模型ĺŤç¨±', + modelUid: '模型uid', + modelType: '模型類型', + addLlmBaseUrl: '基礎 Url', + vision: 'ćŻĺ¦ć”ŻćŚVision', + modelNameMessage: '請輸入模型ĺŤç¨±ďĽ', + modelTypeMessage: '請輸入模型類型ďĽ', + baseUrlNameMessage: '請輸入基礎 UrlďĽ', + ollamaLink: '如何集ćOllama', + }, + 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: 'â€śäżťç•™ć‰€ćś‰ć¬Šĺ© @ react”', + }, + layout: { + file: '文件', + knowledge: '知č', + chat: 'čŠĺ¤©', + }, + }, +}; diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index ad4741a..0b2a86e 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -15,7 +15,8 @@ export default { edit: '编辑', upload: 'ä¸ŠäĽ ', english: '英文', - chinese: 'ä¸ć–‡', + chinese: 'ä¸ć–‡ç®€ä˝“', + traditionalChinese: 'ä¸ć–‡çąä˝“', language: 'čŻč¨€', languageMessage: '请输入čŻč¨€', languagePlaceholder: '请选择čŻč¨€', diff --git a/web/src/pages/user-setting/model.ts b/web/src/pages/user-setting/model.ts index da2ceed..6ac5782 100644 --- a/web/src/pages/user-setting/model.ts +++ b/web/src/pages/user-setting/model.ts @@ -1,3 +1,4 @@ +import { LanguageTranslationMap } from '@/constants/common'; import { ITenantInfo } from '@/interfaces/database/knowledge'; import { IFactory, @@ -66,7 +67,11 @@ const model: DvaModel<SettingModelState> = { // }; // authorizationUtil.setUserInfo(userInfo); if (retcode === 0) { - i18n.changeLanguage(res.language === 'Chinese' ? 'zh' : 'en'); + i18n.changeLanguage( + LanguageTranslationMap[ + res.language as keyof typeof LanguageTranslationMap + ], + ); yield put({ type: 'setUserInfo', payload: res }); // localStorage.setItem('userInfo',res.) } diff --git a/web/src/pages/user-setting/setting-profile/index.tsx b/web/src/pages/user-setting/setting-profile/index.tsx index 627af93..e2422a9 100644 --- a/web/src/pages/user-setting/setting-profile/index.tsx +++ b/web/src/pages/user-setting/setting-profile/index.tsx @@ -20,6 +20,7 @@ import { Upload, UploadFile, } from 'antd'; +import camelCase from 'lodash/camelCase'; import { useEffect } from 'react'; import SettingTitle from '../components/setting-title'; import { TimezoneList } from '../constants'; @@ -29,6 +30,7 @@ import { useValidateSubmittable, } from '../hooks'; +import { LanguageList } from '@/constants/common'; import { useTranslate } from '@/hooks/commonHooks'; import { useChangeLanguage } from '@/hooks/logicHooks'; import parentStyles from '../index.less'; @@ -162,12 +164,11 @@ const UserSettingProfile = () => { placeholder={t('languagePlaceholder', { keyPrefix: 'common' })} onChange={changeLanguage} > - <Option value="English"> - {t('english', { keyPrefix: 'common' })} - </Option> - <Option value="Chinese"> - {t('chinese', { keyPrefix: 'common' })} - </Option> + {LanguageList.map((x) => ( + <Option value={x} key={x}> + {t(camelCase(x), { keyPrefix: 'common' })} + </Option> + ))} </Select> </Form.Item> <Divider /> -- GitLab