diff --git a/web/src/app/home/components/home-sidebar/HomeSidebar.tsx b/web/src/app/home/components/home-sidebar/HomeSidebar.tsx
index 876baf33..fa435cf7 100644
--- a/web/src/app/home/components/home-sidebar/HomeSidebar.tsx
+++ b/web/src/app/home/components/home-sidebar/HomeSidebar.tsx
@@ -144,6 +144,11 @@ export default function HomeSidebar({
'https://docs.langbot.app/zh/insight/guide.html',
'_blank',
);
+ } else if (language === 'zh-Hant') {
+ window.open(
+ 'https://docs.langbot.app/zh/insight/guide.html',
+ '_blank',
+ );
} else {
window.open(
'https://docs.langbot.app/en/insight/guide.html',
diff --git a/web/src/app/login/page.tsx b/web/src/app/login/page.tsx
index d55e3fd3..3a5e22e3 100644
--- a/web/src/app/login/page.tsx
+++ b/web/src/app/login/page.tsx
@@ -65,6 +65,9 @@ export default function Login() {
if (i18n.language === 'zh-CN' || i18n.language === 'zh-Hans') {
setCurrentLanguage('zh-Hans');
localStorage.setItem('langbot_language', 'zh-Hans');
+ } else if (i18n.language === 'zh-TW' || i18n.language === 'zh-Hant') {
+ setCurrentLanguage('zh-Hant');
+ localStorage.setItem('langbot_language', 'zh-Hant');
} else if (i18n.language === 'ja' || i18n.language === 'ja-JP') {
setCurrentLanguage('ja-JP');
localStorage.setItem('langbot_language', 'ja-JP');
@@ -84,6 +87,8 @@ export default function Login() {
let lang = 'zh-Hans';
if (language === 'zh-CN') {
lang = 'zh-Hans';
+ } else if (language === 'zh-TW') {
+ lang = 'zh-Hant';
} else if (language === 'ja' || language === 'ja-JP') {
lang = 'ja-JP';
} else {
@@ -164,6 +169,7 @@ export default function Login() {
简体中文
+ 繁體中文
English
日本語
diff --git a/web/src/app/register/page.tsx b/web/src/app/register/page.tsx
index d885f3b0..56ae7e9c 100644
--- a/web/src/app/register/page.tsx
+++ b/web/src/app/register/page.tsx
@@ -63,6 +63,9 @@ export default function Register() {
if (i18n.language === 'zh-CN' || i18n.language === 'zh-Hans') {
setCurrentLanguage('zh-Hans');
localStorage.setItem('langbot_language', 'zh-Hans');
+ } else if (i18n.language === 'zh-TW' || i18n.language === 'zh-Hant') {
+ setCurrentLanguage('zh-Hant');
+ localStorage.setItem('langbot_language', 'zh-Hant');
} else if (i18n.language === 'ja' || i18n.language === 'ja-JP') {
setCurrentLanguage('ja-JP');
localStorage.setItem('langbot_language', 'ja-JP');
@@ -82,6 +85,8 @@ export default function Register() {
let lang = 'zh-Hans';
if (language === 'zh-CN') {
lang = 'zh-Hans';
+ } else if (language === 'zh-TW') {
+ lang = 'zh-Hant';
} else if (language === 'ja' || language === 'ja-JP') {
lang = 'ja-JP';
} else {
@@ -148,6 +153,7 @@ export default function Register() {
简体中文
+ 繁體中文
English
日本語
diff --git a/web/src/i18n/index.ts b/web/src/i18n/index.ts
index fd8f5c7c..74995e00 100644
--- a/web/src/i18n/index.ts
+++ b/web/src/i18n/index.ts
@@ -6,6 +6,7 @@ import LanguageDetector from 'i18next-browser-languagedetector';
import enUS from './locales/en-US';
import zhHans from './locales/zh-Hans';
+import zhHant from './locales/zh-Hant';
import jaJP from './locales/ja-JP';
i18n
@@ -19,6 +20,9 @@ i18n
'zh-Hans': {
translation: zhHans,
},
+ 'zh-Hant': {
+ translation: zhHant,
+ },
'ja-JP': {
translation: jaJP,
},
diff --git a/web/src/i18n/locales/zh-Hant.ts b/web/src/i18n/locales/zh-Hant.ts
new file mode 100644
index 00000000..e71f0e53
--- /dev/null
+++ b/web/src/i18n/locales/zh-Hant.ts
@@ -0,0 +1,330 @@
+const zhHant = {
+ common: {
+ login: '登入',
+ logout: '登出',
+ email: '電子郵件',
+ password: '密碼',
+ welcome: '歡迎回到 LangBot 👋',
+ continueToLogin: '登入以繼續',
+ loginSuccess: '登入成功',
+ loginFailed: '登入失敗,請檢查電子郵件和密碼是否正確',
+ enterEmail: '輸入電子郵件地址',
+ enterPassword: '輸入密碼',
+ invalidEmail: '請輸入有效的電子郵件地址',
+ emptyPassword: '請輸入密碼',
+ language: '語言',
+ helpDocs: '輔助說明',
+ create: '建立',
+ edit: '編輯',
+ delete: '刪除',
+ add: '新增',
+ select: '請選擇',
+ cancel: '取消',
+ submit: '提交',
+ error: '錯誤',
+ success: '成功',
+ save: '儲存',
+ saving: '儲存中...',
+ confirm: '確認',
+ confirmDelete: '確認刪除',
+ deleteConfirmation: '您確定要刪除這個嗎?',
+ selectOption: '選擇一個選項',
+ required: '必填',
+ enable: '是否啟用',
+ name: '名稱',
+ description: '描述',
+ close: '關閉',
+ deleteSuccess: '刪除成功',
+ deleteError: '刪除失敗:',
+ addRound: '新增回合',
+ copySuccess: '複製成功',
+ test: '測試',
+ forgotPassword: '忘記密碼?',
+ loading: '載入中...',
+ },
+ notFound: {
+ title: '頁面不存在',
+ description:
+ '您要查詢的頁面似乎不存在。請檢查您輸入的 URL 是否正確,或返回首頁。',
+ back: '上一級',
+ home: '返回主頁',
+ help: '查看說明文件',
+ },
+ models: {
+ title: '模型設定',
+ description: '設定和管理可在流程線中使用的模型',
+ createModel: '建立模型',
+ editModel: '編輯模型',
+ getModelListError: '取得模型清單失敗:',
+ modelName: '模型名稱',
+ modelProvider: '模型供應商',
+ modelBaseURL: '基礎 URL',
+ modelAbilities: '模型能力',
+ saveSuccess: '儲存成功',
+ saveError: '儲存失敗:',
+ createSuccess: '建立成功',
+ createError: '建立失敗:',
+ deleteSuccess: '刪除成功',
+ deleteError: '刪除失敗:',
+ deleteConfirmation: '您確定要刪除這個模型嗎?',
+ modelNameRequired: '模型名稱不能為空',
+ modelProviderRequired: '模型供應商不能為空',
+ requestURLRequired: '請求URL不能為空',
+ apiKeyRequired: 'API Key不能為空',
+ keyNameRequired: '鍵名不能為空',
+ mustBeValidNumber: '必須是有效的數字',
+ mustBeTrueOrFalse: '必須是 true 或 false',
+ requestURL: '請求URL',
+ apiKey: 'API Key',
+ abilities: '能力',
+ selectModelAbilities: '選擇模型能力',
+ visionAbility: '視覺能力',
+ functionCallAbility: '函數呼叫',
+ extraParameters: '額外參數',
+ addParameter: '新增參數',
+ keyName: '鍵名',
+ type: '類型',
+ value: '值',
+ string: '字串',
+ number: '數字',
+ boolean: '布林值',
+ selectModelProvider: '選擇模型供應商',
+ modelProviderDescription: '請填寫供應商向您提供的模型名稱',
+ selectModel: '請選擇模型',
+ testSuccess: '測試成功',
+ testError: '測試失敗,請檢查模型設定',
+ llmModels: '對話模型',
+ },
+ bots: {
+ title: '機器人',
+ description: '建立和管理機器人,這是 LangBot 與各個平台連接的入口',
+ createBot: '建立機器人',
+ editBot: '編輯機器人',
+ getBotListError: '取得機器人清單失敗:',
+ botName: '機器人名稱',
+ botDescription: '機器人描述',
+ botNameRequired: '機器人名稱不能為空',
+ botDescriptionRequired: '機器人描述不能為空',
+ adapterRequired: '適配器不能為空',
+ defaultDescription: '一個機器人',
+ getBotConfigError: '取得機器人設定失敗:',
+ saveSuccess: '儲存成功',
+ saveError: '儲存失敗:',
+ createSuccess: '建立成功 請啟用或修改綁定流程線',
+ createError: '建立失敗:',
+ deleteSuccess: '刪除成功',
+ deleteError: '刪除失敗:',
+ deleteConfirmation: '您確定要刪除這個機器人嗎?',
+ platformAdapter: '平台/適配器選擇',
+ selectAdapter: '選擇適配器',
+ adapterConfig: '適配器設定',
+ bindPipeline: '綁定流程線',
+ selectPipeline: '選擇流程線',
+ botLogTitle: '機器人日誌',
+ enableAutoRefresh: '開啟自動重新整理',
+ session: '對話',
+ yesterday: '昨天',
+ earlier: '更久之前',
+ dateFormat: '{{month}}月{{day}}日',
+ setBotEnableError: '設定機器人啟用狀態失敗',
+ log: '日誌',
+ configuration: '設定',
+ logs: '日誌',
+ },
+ plugins: {
+ title: '外掛管理',
+ description: '安裝和設定用於擴展 LangBot 功能的外掛',
+ createPlugin: '建立外掛',
+ editPlugin: '編輯外掛',
+ installed: '已安裝',
+ marketplace: 'Marketplace',
+ arrange: '編排',
+ install: '安裝',
+ installFromGithub: '從 GitHub 安裝外掛',
+ onlySupportGithub: '目前僅支援從 GitHub 安裝',
+ enterGithubLink: '請輸入外掛的Github連結',
+ installing: '正在安裝外掛...',
+ installSuccess: '外掛安裝成功',
+ installFailed: '外掛安裝失敗:',
+ searchPlugin: '搜尋外掛',
+ sortBy: '排序方式',
+ mostStars: '最多星標',
+ recentlyAdded: '最近新增',
+ recentlyUpdated: '最近更新',
+ noMatchingPlugins: '沒有找到符合的外掛',
+ loading: '載入中...',
+ getPluginListError: '取得外掛清單失敗:',
+ pluginConfig: '外掛設定',
+ noPluginInstalled: '暫未安裝任何外掛',
+ pluginSort: '外掛排序',
+ pluginSortDescription:
+ '外掛順序會影響同一事件內的處理順序,請拖曳外掛卡片排序',
+ pluginSortSuccess: '外掛排序成功',
+ pluginSortError: '外掛排序失敗:',
+ pluginNoConfig: '外掛沒有設定項目。',
+ deleting: '刪除中...',
+ deletePlugin: '刪除外掛',
+ cancel: '取消',
+ saveConfig: '儲存設定',
+ saving: '儲存中...',
+ confirmDeletePlugin: '您確定要刪除外掛({{author}}/{{name}})嗎?',
+ confirmDelete: '確認刪除',
+ deleteError: '刪除失敗:',
+ close: '關閉',
+ deleteConfirm: '刪除確認',
+ modifyFailed: '修改失敗:',
+ eventCount: '事件:{{count}}',
+ toolCount: '工具:{{count}}',
+ starCount: '星標:{{count}}',
+ },
+ pipelines: {
+ title: '流程線',
+ description: '流程線定義了對訊息事件的處理流程,用於綁定到機器人',
+ createPipeline: '建立流程線',
+ editPipeline: '編輯流程線',
+ chat: '對話',
+ configuration: '設定',
+ debugChat: '對話除錯',
+ getPipelineListError: '取得流程線清單失敗:',
+ daysAgo: '天前',
+ today: '今天',
+ updateTime: '更新於',
+ defaultBadge: '預設',
+ sortBy: '排序方式',
+ newestCreated: '最新建立',
+ recentlyEdited: '最近編輯',
+ earliestEdited: '最早編輯',
+ basicInfo: '基本資訊',
+ aiCapabilities: 'AI 能力',
+ triggerConditions: '觸發條件',
+ safetyControls: '安全控制',
+ outputProcessing: '輸出處理',
+ nameRequired: '名稱不能為空',
+ descriptionRequired: '描述不能為空',
+ createSuccess: '建立成功 請編輯流程線詳細參數',
+ createError: '建立失敗:',
+ saveSuccess: '儲存成功',
+ saveError: '儲存失敗:',
+ deleteConfirmation:
+ '您確定要刪除這個流程線嗎?已綁定此流程線的機器人將無法使用。',
+ defaultPipelineCannotDelete: '預設流程線不可刪除',
+ deleteSuccess: '刪除成功',
+ deleteError: '刪除失敗:',
+ debugDialog: {
+ title: '流程線對話',
+ selectPipeline: '選擇流程線',
+ sessionType: '對話類型',
+ privateChat: '私聊',
+ groupChat: '群聊',
+ send: '傳送',
+ reset: '重設對話',
+ inputPlaceholder: '傳送 {{type}} 訊息...',
+ noMessages: '暫無訊息',
+ userMessage: '使用者',
+ botMessage: '機器人',
+ sendFailed: '傳送失敗',
+ resetSuccess: '對話已重設',
+ resetFailed: '重設失敗',
+ loadMessagesFailed: '載入訊息失敗',
+ loadPipelinesFailed: '載入流程線失敗',
+ atTips: '提及機器人',
+ },
+ },
+ knowledge: {
+ title: '知識庫',
+ createKnowledgeBase: '建立知識庫',
+ editKnowledgeBase: '編輯知識庫',
+ selectKnowledgeBase: '選擇知識庫',
+ empty: '無',
+ editDocument: '文件',
+ description: '設定可用於提升模型回覆品質的知識庫',
+ metadata: '中繼資料',
+ documents: '文件',
+ kbNameRequired: '知識庫名稱不能為空',
+ kbDescriptionRequired: '知識庫描述不能為空',
+ embeddingModelUUIDRequired: '嵌入模型不能為空',
+ daysAgo: '天前',
+ today: '今天',
+ kbName: '知識庫名稱',
+ kbDescription: '知識庫描述',
+ defaultDescription: '一個知識庫',
+ embeddingModelUUID: '嵌入模型',
+ selectEmbeddingModel: '選擇嵌入模型',
+ embeddingModelDescription: '用於向量化文字,可在模型設定頁面設定',
+ updateTime: '更新於',
+ cannotChangeEmbeddingModel: '知識庫建立後不可修改嵌入模型',
+ updateKnowledgeBaseSuccess: '知識庫更新成功',
+ updateKnowledgeBaseFailed: '知識庫更新失敗',
+ documentsTab: {
+ name: '名稱',
+ status: '狀態',
+ noResults: '暫無文件',
+ dragAndDrop: '拖曳檔案到此處或點擊上傳',
+ uploading: '上傳中...',
+ supportedFormats: '支援 PDF、Word、TXT、Markdown 等文件格式',
+ uploadSuccess: '檔案上傳成功!',
+ uploadError: '檔案上傳失敗,請重試',
+ uploadingFile: '上傳檔案中...',
+ actions: '操作',
+ delete: '刪除檔案',
+ fileDeleteSuccess: '檔案刪除成功',
+ fileDeleteFailed: '檔案刪除失敗',
+ processing: '處理中',
+ completed: '完成',
+ failed: '失敗',
+ },
+ deleteKnowledgeBaseConfirmation:
+ '您確定要刪除這個知識庫嗎?此知識庫下的所有文件將被刪除。',
+ retrieve: '檢索測試',
+ retrieveTest: '檢索測試',
+ query: '查詢',
+ queryPlaceholder: '輸入查詢內容...',
+ distance: '距離',
+ content: '內容',
+ fileName: '檔案名稱',
+ noResults: '暫無結果',
+ retrieveError: '檢索失敗',
+ },
+ register: {
+ title: '初始化 LangBot 👋',
+ description: '這是您首次啟動 LangBot',
+ adminAccountNote: '您填寫的電子郵件和密碼將作為初始管理員帳號',
+ register: '註冊',
+ initSuccess: '初始化成功 請登入',
+ initFailed: '初始化失敗:',
+ },
+ resetPassword: {
+ title: '重設密碼 🔐',
+ description: '輸入恢復金鑰和新的密碼來重設您的帳戶密碼',
+ recoveryKey: '恢復金鑰',
+ recoveryKeyDescription:
+ '儲存在設定檔案`data/config.yaml`的`system.recovery_key`中',
+ newPassword: '新密碼',
+ enterRecoveryKey: '輸入恢復金鑰',
+ enterNewPassword: '輸入新密碼',
+ recoveryKeyRequired: '恢復金鑰不能為空',
+ newPasswordRequired: '新密碼不能為空',
+ resetPassword: '重設密碼',
+ resetting: '重設中...',
+ resetSuccess: '密碼重設成功,請登入',
+ resetFailed: '密碼重設失敗,請檢查電子郵件和恢復金鑰是否正確',
+ backToLogin: '返回登入',
+ },
+ embedding: {
+ description: '管理嵌入模型,用於向量化文字',
+ createModel: '建立嵌入模型',
+ editModel: '編輯嵌入模型',
+ getModelListError: '取得嵌入模型清單失敗:',
+ embeddingModels: '嵌入模型',
+ extraParametersDescription:
+ '將在請求時附加到請求體中,如 encoding_format, dimensions 等',
+ },
+ llm: {
+ llmModels: '對話模型',
+ description: '管理 LLM 模型,用於對話訊息產生',
+ extraParametersDescription:
+ '將在請求時附加到請求體中,如 max_tokens, temperature, top_p 等',
+ },
+};
+
+export default zhHant;