diff --git a/backend/apps/chat/task/llm.py b/backend/apps/chat/task/llm.py index dd314fd0..4193029d 100644 --- a/backend/apps/chat/task/llm.py +++ b/backend/apps/chat/task/llm.py @@ -1832,6 +1832,8 @@ def get_lang_name(lang: str): if not lang: return '简体中文' normalized = lang.lower() + if normalized.startswith('zh-tw'): + return '繁体中文' if normalized.startswith('en'): return '英文' if normalized.startswith('ko'): diff --git a/backend/apps/system/api/user.py b/backend/apps/system/api/user.py index 84e72962..58033543 100644 --- a/backend/apps/system/api/user.py +++ b/backend/apps/system/api/user.py @@ -273,7 +273,7 @@ async def batch_del(session: SessionDep, id_list: list[int]): @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id") async def langChange(session: SessionDep, current_user: CurrentUser, trans: Trans, language: UserLanguage): lang = language.language - if lang not in ["zh-CN", "en", "ko-KR"]: + if lang not in ["zh-CN", "zh-TW", "en", "ko-KR"]: raise Exception(trans('i18n_user.language_not_support', key = lang)) db_user: UserModel = get_db_user(session=session, user_id=current_user.id) db_user.language = lang diff --git a/backend/apps/system/schemas/system_schema.py b/backend/apps/system/schemas/system_schema.py index 5be16668..87b1a41d 100644 --- a/backend/apps/system/schemas/system_schema.py +++ b/backend/apps/system/schemas/system_schema.py @@ -32,7 +32,7 @@ class BaseUser(BaseModel): class BaseUserDTO(BaseUser, BaseCreatorDTO): - language: str = Field(pattern=r"^(zh-CN|en|ko-KR)$", default="zh-CN", description="用户语言") + language: str = Field(pattern=r"^(zh-CN|zh-TW|en|ko-KR)$", default="zh-CN", description="用户语言") password: str status: int = 1 origin: int = 0 @@ -47,8 +47,8 @@ def to_dict(self): @field_validator("language") def validate_language(cls, lang: str) -> str: - if not re.fullmatch(r"^(zh-CN|en|ko-KR)$", lang): - raise ValueError("Language must be 'zh-CN', 'en', or 'ko-KR'") + if not re.fullmatch(r"^(zh-CN|zh-TW|en|ko-KR)$", lang): + raise ValueError("Language must be 'zh-CN', 'zh-TW', 'en', or 'ko-KR'") return lang diff --git a/backend/locales/zh-TW.json b/backend/locales/zh-TW.json new file mode 100644 index 00000000..0bb90867 --- /dev/null +++ b/backend/locales/zh-TW.json @@ -0,0 +1,197 @@ +{ + "i18n_default_workspace": "默認工作空間", + "i18n_ds_name_exist": "名稱已存在", + "i18n_concat_admin": "請聯繫管理員!", + "i18n_exist": "{msg}已存在!", + "i18n_name": "名稱", + "i18n_not_exist": "{msg}不存在!", + "i18n_error": "{key}錯誤!", + "i18n_miss_args": "缺失{key}參數!", + "i18n_format_invalid": "{key}格式不正確!", + "i18n_login": { + "account_pwd_error": "帳號或密碼錯誤!", + "no_associated_ws": "沒有關聯的工作空間,{msg}", + "user_disable": "帳號已禁用,{msg}", + "origin_error": "登入方式錯誤", + "prohibit_auto_create": "禁止自動建立用戶,請先同步用戶", + "no_platform_user": "帳號不存在,請先同步用戶" + }, + "i18n_user": { + "account": "帳號", + "email": "郵箱", + "password": "密碼", + "language_not_support": "系統不支援[{key}]語言!", + "ws_miss": "當前用戶不在工作空間[{ws}]中!", + "name": "姓名", + "status": "用戶狀態", + "origin": "用戶來源", + "workspace": "工作空間", + "role": "角色", + "platform_user_id": "外部用戶唯一標識", + "administrator": "管理員", + "ordinary_member": "普通成員", + "status_enabled": "已啟用", + "status_disabled": "已禁用", + "local_creation": "本地建立" + }, + "i18n_ws": { + "title": "工作空間" + }, + "i18n_permission": { + "only_admin": "僅支援管理員調用!", + "no_permission": "無權調用{url}{msg}", + "authenticate_invalid": "認證無效【{msg}】", + "token_expired": "Token 已過期", + "only_ws_admin": "僅支援工作空間管理員調用!", + "permission_resource_limit": "沒有操作權限或資源不存在!" + }, + "i18n_llm": { + "validate_error": "校驗失敗[{msg}]", + "delete_default_error": "無法刪除默認模型[{key}]!", + "miss_default": "尚未配置默認大語言模型" + }, + "i18n_ds_invalid": "數據源連接無效", + "i18n_embedded": { + "invalid_origin": "網域校驗失敗【{origin}】" + }, + "i18n_chat": { + "record_id_in_mcp": "響應ID: " + }, + "i18n_terminology": { + "terminology_not_exists": "該術語不存在", + "datasource_cannot_be_none": "數據源不能為空", + "cannot_be_repeated": "術語名稱,同義詞不能重複", + "exists_in_db": "術語名稱,同義詞已存在", + "term_name": "術語名稱", + "term_description": "術語描述", + "effective_data_sources": "生效數據源", + "all_data_sources": "所有數據源", + "synonyms": "同義詞", + "term_name_template": "術語名稱(必填)", + "term_description_template": "術語描述(必填)", + "effective_data_sources_template": "生效數據源(支援多個,用\",\"分割)", + "all_data_sources_template": "所有數據源(Y:應用到全部數據源,N:應用到指定數據源)", + "synonyms_template": "同義詞(支援多個,用\",\"分割)", + "term_name_template_example_1": "術語1", + "term_description_template_example_1": "術語1描述", + "effective_data_sources_template_example_1": "生效數據源1, 生效數據源2", + "synonyms_template_example_1": "同義詞1, 同義詞2", + "term_name_template_example_2": "術語2", + "term_description_template_example_2": "術語2描述", + "synonyms_template_example_2": "同義詞3", + "word_cannot_be_empty": "術語名稱不能為空", + "description_cannot_be_empty": "術語描述不能為空", + "datasource_not_found": "找不到數據源" + }, + "i18n_data_training": { + "datasource_list_is_not_found": "數據源列表未找到", + "datasource_id_not_found": "數據源ID: {key} 未找到", + "datasource_cannot_be_none": "數據源不能為空", + "datasource_assistant_cannot_be_none": "數據源或高級應用不能都為空", + "data_training_not_exists": "該範例不存在", + "exists_in_db": "該問題已存在", + "data_training": "SQL 範例庫", + "problem_description": "問題描述", + "sample_sql": "範例 SQL", + "effective_data_sources": "生效數據源", + "advanced_application": "高級應用", + "problem_description_template": "問題描述(必填)", + "sample_sql_template": "範例 SQL(必填)", + "effective_data_sources_template": "生效數據源", + "advanced_application_template": "高級應用", + "problem_description_template_example": "查詢TEST表內所有ID", + "effective_data_sources_template_example": "生效數據源1", + "advanced_application_template_example": "生效高級應用名稱", + "error_info": "錯誤訊息", + "question_cannot_be_empty": "問題不能為空", + "description_cannot_be_empty": "範例 SQL 不能為空", + "datasource_not_found": "找不到數據源", + "advanced_application_not_found": "找不到高級應用" + }, + "i18n_custom_prompt": { + "exists_in_db": "模版名稱已存在", + "not_exists": "該模版不存在", + "prompt_word_name": "提示詞名稱", + "prompt_word_content": "提示詞內容", + "effective_data_sources": "生效數據源", + "all_data_sources": "所有數據源", + "prompt_word_name_template": "提示詞名稱(必填)", + "prompt_word_content_template": "提示詞內容(必填)", + "effective_data_sources_template": "生效數據源(支援多個,用\",\"分割)", + "all_data_sources_template": "所有數據源(Y:應用到全部數據源,N:應用到指定數據源)", + "prompt_word_name_template_example1": "提示詞1", + "prompt_word_content_template_example1": "詳細描述你的提示詞", + "effective_data_sources_template_example1": "生效數據源1, 生效數據源2", + "prompt_word_name_template_example2": "提示詞2", + "prompt_word_content_template_example2": "詳細描述你的提示詞", + "name_cannot_be_empty": "名稱不能為空", + "prompt_cannot_be_empty": "提示詞內容不能為空", + "type_cannot_be_empty": "類型不能為空", + "datasource_not_found": "找不到數據源", + "datasource_cannot_be_none": "數據源不能為空" + }, + "i18n_excel_export": { + "data_is_empty": "表單數據為空,無法導出數據" + }, + "i18n_excel_import": { + "col_num_not_match": "EXCEL列數量不匹配" + }, + "i18n_authentication": { + "record_not_exist": "{msg} 記錄不存在,請先儲存!" + }, + "i18n_audit": { + "success": "成功", + "failed": "失敗", + "system_log": "操作日誌", + "operation_type_name": "操作類型", + "operation_detail_info": "操作詳情", + "user_name": "操作用戶", + "oid_name": "工作空間", + "operation_status_name": "操作狀態", + "error_message": "錯誤訊息", + "ip_address": "IP 地址", + "create_time": "操作時間", + "chat": "智能問數", + "datasource": "數據源", + "dashboard": "儀表板", + "member": "成員", + "permission": "權限", + "terminology": "術語", + "data_training": "SQL 範例庫", + "prompt_words": "提示詞", + "user": "用戶", + "workspace": "工作空間", + "ai_model": "AI 模型", + "application": "應用", + "theme": "外觀配置", + "create": "新建", + "delete": "刪除", + "update": "更新", + "edit": "編輯", + "login": "登入", + "export": "匯出", + "import": "匯入", + "add": "新增", + "create_or_update": "變更", + "api_key": "API Key", + "params_setting": "參數配置", + "rules": "權限規則", + "log_setting": "登入認證", + "setting": "設定", + "system_management": "系統管理", + "opt_log": "操作日誌", + "prediction": "數據預測", + "analysis": "數據分析", + "reset_pwd": "重置密碼", + "update_pwd": "更新密碼", + "update_status": "更新狀態", + "update_table_relation": "變更表關係" + }, + "i18n_table_not_exist": "當前表不存在", + "i18n_variable": { + "name_exist": "變數名稱已存在", + "name": "姓名", + "account": "帳號", + "email": "郵箱" + } +} \ No newline at end of file