From 989ab0c6315b7f8063d6530f1cb4a1584b0f3305 Mon Sep 17 00:00:00 2001 From: swakinx Date: Thu, 24 Sep 2026 21:55:49 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=8C=90=20feat:=20Add=20Simplified=20C?= =?UTF-8?q?hinese=20(zh-Hans)=20locale?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add src/locales/zh-Hans/translation.json covering the full en key set (terminology aligned with the LibreChat main zh-Hans translation) - Register zh-Hans in i18n init with LibreChat-style locale normalization and detection (stored choice > navigator, alias mapping zh/zh-CN/zh-SG), replacing the browser-languagedetector whose nonExplicitSupportedLngs handling rejected zh-Hans - Render the SSR loading shell in the default locale deterministically and suppress the expected hydration text mismatch - Guard en/zh key-set and placeholder parity plus language switching in locales.test.ts --- src/locales/i18n.ts | 79 +- src/locales/locales.test.ts | 65 ++ src/locales/zh-Hans/translation.json | 1238 ++++++++++++++++++++++++++ src/routes/__root.tsx | 4 +- 4 files changed, 1370 insertions(+), 16 deletions(-) create mode 100644 src/locales/locales.test.ts create mode 100644 src/locales/zh-Hans/translation.json diff --git a/src/locales/i18n.ts b/src/locales/i18n.ts index 4b261ee0..37254c0d 100644 --- a/src/locales/i18n.ts +++ b/src/locales/i18n.ts @@ -1,27 +1,76 @@ import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; -import LanguageDetector from 'i18next-browser-languagedetector'; import translationEn from './en/translation.json'; +import translationZhHans from './zh-Hans/translation.json'; export const defaultNS = 'translation'; +export const supportedLocales = ['en', 'zh-Hans'] as const; +export type SupportedLocale = (typeof supportedLocales)[number]; + export const resources = { en: { translation: translationEn }, + 'zh-Hans': { translation: translationZhHans }, } as const; -i18n - .use(LanguageDetector) - .use(initReactI18next) - .init({ - fallbackLng: { - default: ['en'], - }, - fallbackNS: 'translation', - ns: ['translation'], - debug: false, - defaultNS, - resources, - interpolation: { escapeValue: false }, - }); +const supportedByLowercase: Record = Object.fromEntries( + supportedLocales.map((locale) => [locale.toLowerCase(), locale]), +); + +// Mirrors LibreChat's client locale normalization: exact supported match first, +// then alias table, then the base-language entry. +const localeAliases: Record = { + zh: 'zh-Hans', + 'zh-cn': 'zh-Hans', + 'zh-sg': 'zh-Hans', +}; + +export function normalizeLocale(locale?: string | null): SupportedLocale { + if (!locale) { + return 'en'; + } + const normalized = locale.replace(/_/g, '-').toLowerCase(); + const exact = supportedByLowercase[normalized]; + if (exact) { + return exact; + } + return localeAliases[normalized] ?? localeAliases[normalized.split('-')[0]] ?? 'en'; +} + +// A stored choice (i18nextLng, written by the settings language selector) wins; +// otherwise fall back to the browser language. SSR has no reliable locale +// signal (Bun defines `navigator` but leaves `language` empty), so it always +// renders the default locale and the browser takes over on hydration. +export function detectInitialLanguage(): SupportedLocale { + if (typeof window === 'undefined') { + return 'en'; + } + const stored = localStorage.getItem('i18nextLng'); + if (stored) { + return normalizeLocale(stored); + } + return normalizeLocale(navigator.language || navigator.languages?.[0]); +} + +const initialLanguage = detectInitialLanguage(); + +i18n.use(initReactI18next).init({ + lng: initialLanguage, + supportedLngs: [...supportedLocales], + fallbackLng: { + zh: ['zh-Hans'], + default: ['en'], + }, + fallbackNS: 'translation', + ns: ['translation'], + debug: false, + defaultNS, + resources, + interpolation: { escapeValue: false }, +}); + +if (typeof document !== 'undefined') { + document.documentElement.lang = initialLanguage; +} export default i18n; diff --git a/src/locales/locales.test.ts b/src/locales/locales.test.ts new file mode 100644 index 00000000..94dda990 --- /dev/null +++ b/src/locales/locales.test.ts @@ -0,0 +1,65 @@ +/** + * Guards locale parity between en and zh-Hans: identical key sets, + * matching interpolation placeholders, and a working language switch. + */ +import { describe, it, expect } from 'vitest'; +import i18n, { normalizeLocale, detectInitialLanguage } from './i18n'; +import en from './en/translation.json'; +import zhHans from './zh-Hans/translation.json'; + +const enKeys = Object.keys(en).sort(); +const zhKeys = Object.keys(zhHans).sort(); + +describe('locale parity (en / zh-Hans)', () => { + it('zh-Hans defines the same key set as en', () => { + expect(zhKeys).toEqual(enKeys); + }); + + it('interpolation placeholders match en for every key', () => { + const re = /\{\{[^}]+\}\}/g; + const mismatches = enKeys.filter( + (key) => + (String(en[key as keyof typeof en]).match(re) ?? []).sort().join() !== + (String(zhHans[key as keyof typeof zhHans]).match(re) ?? []).sort().join(), + ); + expect(mismatches).toHaveLength(0); + }); + + it('switches to zh-Hans and back', async () => { + await i18n.changeLanguage('zh-Hans'); + expect(i18n.t('com_ui_save')).toBe(zhHans['com_ui_save']); + await i18n.changeLanguage('en'); + expect(i18n.t('com_ui_save')).toBe(en['com_ui_save']); + }); + + it('resolves browser-style zh codes to zh-Hans', async () => { + await i18n.changeLanguage('zh-CN'); + expect(i18n.t('com_ui_save')).toBe(zhHans['com_ui_save']); + await i18n.changeLanguage('zh'); + expect(i18n.t('com_ui_save')).toBe(zhHans['com_ui_save']); + await i18n.changeLanguage('en'); + expect(i18n.t('com_ui_save')).toBe(en['com_ui_save']); + }); +}); + +describe('locale normalization (LibreChat-style)', () => { + it('maps exact, alias, and base-language codes to supported locales', () => { + expect(normalizeLocale(null)).toBe('en'); + expect(normalizeLocale('en')).toBe('en'); + expect(normalizeLocale('en-US')).toBe('en'); + expect(normalizeLocale('zh-CN')).toBe('zh-Hans'); + expect(normalizeLocale('zh')).toBe('zh-Hans'); + expect(normalizeLocale('zh-Hans')).toBe('zh-Hans'); + expect(normalizeLocale('zh_TW')).toBe('zh-Hans'); + expect(normalizeLocale('zh-TW')).toBe('zh-Hans'); + expect(normalizeLocale('fr')).toBe('en'); + }); + + it('prefers a stored choice over the browser language', () => { + localStorage.setItem('i18nextLng', 'zh-Hans'); + expect(detectInitialLanguage()).toBe('zh-Hans'); + localStorage.setItem('i18nextLng', 'en'); + expect(detectInitialLanguage()).toBe('en'); + localStorage.removeItem('i18nextLng'); + }); +}); diff --git a/src/locales/zh-Hans/translation.json b/src/locales/zh-Hans/translation.json new file mode 100644 index 00000000..963560b4 --- /dev/null +++ b/src/locales/zh-Hans/translation.json @@ -0,0 +1,1238 @@ +{ + "com_ui_read_more": "查看更多", + "com_ui_add_item": "添加{{item}}", + "com_ui_delete": "删除", + "com_ui_clear": "清除", + "com_a11y_clear_dates": "清除日期筛选", + "com_a11y_copy_failed": "复制失败。你的浏览器可能阻止了剪贴板访问。", + "com_audit_detail_copied": "已复制!", + "com_ui_remove_item": "移除{{name}}", + "com_ui_save": "保存", + "com_ui_add": "添加", + "com_ui_cancel": "取消", + "com_ui_create": "创建", + "com_ui_retry": "重试", + "com_ui_done": "完成", + "com_ui_enabled": "已启用", + "com_ui_disabled": "已禁用", + "com_ui_no_items": "未配置任何{{item}}", + "com_ui_search": "搜索", + "com_ui_loading": "加载中...", + "com_ui_select": "选择...", + "com_ui_enter_value": "输入值...", + "com_ui_enter_number": "输入数字...", + "com_ui_enter_text": "输入文本...", + "com_ui_enter_url": "https://...", + "com_ui_key": "键", + "com_ui_value": "值", + "com_ui_entry": "条目", + "com_ui_item": "条目", + "com_ui_sign_out": "退出登录", + "com_ui_signing_out": "正在退出登录...", + "com_ui_items_count": "{{count}} 项", + "com_ui_properties_count": "{{count}} 个属性", + "com_ui_invalid_json": "无效的 JSON", + "com_ui_invalid_yaml": "无效的 YAML", + "com_ui_dismiss": "关闭", + "com_ui_edit_json": "以 JSON 编辑...", + "com_ui_edit_yaml": "以 YAML 编辑...", + "com_ui_true": "是", + "com_ui_false": "否", + "com_ui_reset": "重置", + "com_nav_user_menu": "用户菜单", + "com_nav_users": "用户", + "com_nav_groups": "群组", + "com_nav_access": "访问管理", + "com_nav_configuration": "配置", + "com_nav_all_configuration": "全部配置", + "com_nav_help": "帮助", + "com_nav_go_home": "回到首页", + "com_config_title": "配置", + "com_config_subtitle": "查看和管理实例配置设置", + "com_config_loading": "正在加载配置...", + "com_config_select_section": "选择一个区块查看配置", + "com_config_no_results": "未找到配置", + "com_config_local_changes": "示例横幅:管理面板即将上线!", + "com_config_discard": "放弃更改", + "com_config_save": "保存", + "com_config_unsaved_changes": "未保存的更改", + "com_config_unsaved_leave": "有未保存的更改。仍要离开吗?", + "com_config_confirm_save_title": "将更改保存到基础配置?", + "com_config_field_change_count": "{{count}} 个字段将被更新", + "com_config_field_change_count_plural": "{{count}} 个字段将被更新", + "com_config_field_path": "字段", + "com_config_field_before": "变更前", + "com_config_field_after": "变更后", + "com_config_field_added": "已添加", + "com_config_field_removed": "已移除", + "com_config_field_not_set": "未设置", + "com_config_complex_array": "复杂数组编辑即将上线", + "com_config_no_fields": "此区块没有字段", + "com_config_no_entries": "未配置任何条目", + "com_config_customize": "自定义", + "com_config_add_field": "添加字段", + "com_config_select_field": "选择字段...", + "com_config_more_settings": "更多设置", + "com_config_create_endpoint": "创建端点", + "com_config_no_custom_endpoints": "未配置自定义端点", + "com_config_no_mcp_servers": "未配置 MCP 服务器", + "com_config_endpoint_name_required": "端点名称为必填项", + "com_config_create_mcp_server": "创建MCP服务器", + "com_config_server_name": "服务器名称", + "com_config_server_name_required": "服务器名称为必填项", + "com_config_server_name_exists": "已存在同名服务器", + "com_config_server_name_no_dots": "服务器名称不能包含点号", + "com_config_server_name_invalid": "服务器名称不被允许", + "com_config_server_missing_required": "缺少必填字段:{{field}}", + "com_config_mcp_invalid_after_edit": "无法保存:MCP 服务器“{{entry}}”缺少其传输类型所需的字段“{{field}}”。", + "com_config_group_connection": "连接", + "com_config_group_authentication": "认证", + "com_config_group_api_key": "API 密钥", + "com_config_group_oauth": "OAuth 配置", + "com_config_group_server_options": "服务器选项", + "com_config_group_models": "模型", + "com_config_group_title_generation": "标题生成", + "com_config_group_summarization": "摘要", + "com_config_group_advanced": "高级", + "com_config_on_this_page": "本页内容", + "com_config_expand_all": "全部展开", + "com_config_collapse_all": "全部折叠", + "com_config_show_toolbar": "显示工具栏", + "com_config_minimize": "最小化", + "com_config_configured": "已配置", + "com_config_default": "默认", + "com_config_reset_default": "重置为默认值", + "com_config_reset_confirm": "将“{{field}}”重置为默认值?这将移除数据库中的覆盖值。", + "com_config_reset_base": "重置为默认值", + "com_config_reset_base_title": "重置基础配置", + "com_config_reset_base_confirm": "默认情况下,基础配置以本实例的 librechat.yaml 文件(未配置该文件时为内置默认值)为起点,并被你在管理面板中所做的更改覆盖。此操作会将基础配置重置回该起点,且无法撤销。", + "com_config_reset_base_action": "重置为默认值", + "com_config_reset_base_resetting": "正在重置...", + "com_config_reset_base_success": "基础配置已重置为 librechat.yaml", + "com_config_reset_base_dirty": "重置前请先保存或放弃更改", + "com_config_section_configured_count": "已配置 {{count}}/{{total}} 项", + "com_config_default_hint": "(默认:{{value}})", + "com_config_entry_n": "条目 {{n}}", + "com_config_mode_simple": "简单", + "com_config_mode_advanced": "高级", + "com_config_mode_i18n": "按语言", + "com_config_mode_multi": "多行", + "com_config_simplify_disabled": "切换到简单模式前,请先移除多余的语言条目", + "com_config_show_configured_only": "仅显示已配置项", + "com_config_saving": "保存中...", + "com_config_saved": "更改已保存", + "com_config_save_error": "保存失败", + "com_toast_group_created": "群组“{{name}}”已创建", + "com_toast_group_updated": "群组“{{name}}”已更新", + "com_toast_group_deleted": "群组“{{name}}”已删除", + "com_toast_role_created": "角色“{{name}}”已创建", + "com_toast_role_updated": "角色“{{name}}”已更新", + "com_toast_role_deleted": "角色“{{name}}”已删除", + "com_toast_user_invited": "用户“{{name}}”已邀请", + "com_toast_user_deleted": "用户“{{name}}”已删除", + "com_toast_role_assigned": "已添加到角色“{{name}}”", + "com_toast_role_unassigned": "已从角色“{{name}}”移除", + "com_toast_group_assigned": "已添加到群组“{{name}}”", + "com_toast_group_unassigned": "已从群组“{{name}}”移除", + "com_toast_user_profile_created": "已为“{{name}}”创建用户配置档案", + "com_toast_user_profile_deleted": "用户配置档案已删除", + "com_toast_capabilities_saved": "“{{name}}”的能力已保存", + "com_toast_profile_value_saved": "配置档案值已保存", + "com_toast_profile_value_removed": "配置档案值已移除", + "com_config_import_yaml": "导入 YAML", + "com_config_import_yaml_title": "导入配置", + "com_config_import_yaml_desc": "上传或粘贴 librechat.yaml 文件,以填充界面中的配置值。", + "com_config_import_upload": "上传文件", + "com_config_import_paste": "粘贴 YAML", + "com_config_import_choose_file": "选择 .yaml 或 .yml 文件", + "com_config_import_paste_placeholder": "在此粘贴你的 YAML 配置...", + "com_config_import_validate": "校验并导入", + "com_config_import_success": "配置导入成功。", + "com_config_import_error": "导入失败", + "com_config_import_target": "导入目标", + "com_config_import_apply": "应用", + "com_config_import_back": "后退", + "com_config_import_as_base": "基础配置", + "com_config_import_as_base_desc": "更新 librechat.yaml 中的默认设置", + "com_config_import_as_profile": "配置档案", + "com_config_import_as_profile_desc": "将导入的值应用为特定作用域的配置档案设置", + "com_config_import_create_scope": "新建", + "com_config_import_scope_name": "名称", + "com_config_import_scope_name_placeholder": "例如:QA 团队", + "com_config_import_scope_type": "类型", + "com_config_import_scope_priority": "优先级", + "com_config_import_profile_success": "已为 {{name}} 导入 {{count}} 项配置档案值", + "com_config_import_creating": "正在创建作用域...", + "com_config_import_saving": "正在保存配置档案值...", + "com_config_tab_files": "文件与存储", + "com_config_tab_endpoints": "端点", + "com_config_tab_custom_endpoints": "自定义端点", + "com_config_tab_ai_providers": "AI 提供商", + "com_config_tab_model_specs": "模型规格", + "com_config_tab_mcp": "MCP", + "com_config_tab_features": "功能", + "com_config_tab_system": "系统设置", + "com_config_tab_other": "其他", + "com_config_section_interface": "界面", + "com_config_section_interface_desc": "外观与行为", + "com_config_interface_permissions_info": "功能访问权限(提示词、智能体、市场等)请在“访问管理 > 角色”中按角色配置。", + "com_config_section_registration": "注册", + "com_config_section_registration_desc": "用户注册选项", + "com_config_section_speech": "语音", + "com_config_section_speech_desc": "TTS 与 STT 设置", + "com_config_section_model_specs": "模型规格", + "com_config_section_model_specs_desc": "AI 模型配置", + "com_config_section_mcp_servers": "MCP 服务器", + "com_config_section_mcp_servers_desc": "服务器配置", + "com_config_section_rate_limits": "速率限制", + "com_config_section_rate_limits_desc": "API 限流规则", + "com_config_section_balance": "余额", + "com_config_section_balance_desc": "Token 与积分限额", + "com_config_section_file_config": "文件配置", + "com_config_section_file_config_desc": "上传与存储设置", + "com_config_section_actions": "操作", + "com_config_section_actions_desc": "智能体操作处理器", + "com_config_section_web_search": "网络搜索", + "com_config_section_web_search_desc": "搜索提供商设置", + "com_config_section_ocr": "OCR", + "com_config_section_ocr_desc": "文字识别", + "com_config_section_turnstile": "Turnstile", + "com_config_section_turnstile_desc": "验证码设置", + "com_config_section_cache": "缓存", + "com_config_section_cache_desc": "性能缓存", + "com_config_section_version": "版本", + "com_config_section_version_desc": "配置版本", + "com_config_section_file_strategy": "文件策略", + "com_config_section_file_strategy_desc": "存储策略", + "com_config_section_endpoints": "端点", + "com_config_section_endpoints_desc": "自定义端点", + "com_config_section_ai_providers": "AI 提供商", + "com_config_section_ai_providers_desc": "内置 AI 提供商连接", + "com_config_section_memory": "记忆", + "com_config_section_memory_desc": "个性化设置", + "com_config_section_mcp_settings": "MCP 设置", + "com_config_section_mcp_settings_desc": "安全与域名", + "com_config_section_transactions": "交易记录", + "com_config_section_transactions_desc": "日志设置", + "com_config_field_optional": "可选", + "com_config_field_version": "版本", + "com_config_field_cache": "缓存", + "com_config_field_pinned": "已固定", + "com_config_field_promptCacheTtl": "提示词缓存 TTL", + "com_config_field_ocr": "OCR", + "com_config_field_webSearch": "网络搜索", + "com_config_field_memory": "记忆", + "com_config_field_secureImageLinks": "安全图片链接", + "com_config_field_imageOutputType": "图片输出类型", + "com_config_field_includedTools": "包含的工具", + "com_config_field_filteredTools": "排除的工具", + "com_config_field_defaultPinnedTools": "默认固定工具", + "com_config_field_snapshotFiles": "快照文件", + "com_config_field_mcpServers": "MCP 服务器", + "com_config_field_mcpSettings": "MCP 设置", + "com_config_field_interface": "界面", + "com_config_field_turnstile": "Turnstile", + "com_config_field_fileStrategy": "文件策略", + "com_config_field_fileStrategies": "文件策略", + "com_config_field_actions": "操作", + "com_config_field_registration": "注册", + "com_config_field_balance": "余额", + "com_config_field_transactions": "交易记录", + "com_config_field_speech": "语音", + "com_config_field_rateLimits": "速率限制", + "com_config_field_fileConfig": "文件配置", + "com_config_field_modelSpecs": "模型规格", + "com_config_field_endpoints": "端点", + "com_config_field_apiKey": "API 密钥", + "com_config_field_baseURL": "基础 URL", + "com_config_field_url": "URL", + "com_config_field_enabled": "已启用", + "com_config_field_disabled": "已禁用", + "com_config_field_model": "模型", + "com_config_field_models": "模型", + "com_config_field_name": "名称", + "com_config_field_label": "标签", + "com_config_field_description": "描述", + "com_config_field_timeout": "超时", + "com_config_field_headers": "请求头", + "com_config_field_language": "语言", + "com_config_field_languages": "语言", + "com_config_field_region": "区域", + "com_config_field_country": "国家/地区", + "com_config_field_strategy": "策略", + "com_config_field_options": "选项", + "com_config_field_default": "默认", + "com_config_field_type": "类型", + "com_config_field_title": "标题", + "com_config_field_id": "ID", + "com_config_field_provider": "提供商", + "com_config_field_prompt": "提示词", + "com_config_field_placeholder": "占位符", + "com_config_field_quality": "质量", + "com_config_field_mistralModel": "Mistral 模型", + "com_config_field_serperApiKey": "Serper API 密钥", + "com_config_field_searxngInstanceUrl": "SearXNG 实例 URL", + "com_config_field_searxngApiKey": "SearXNG API 密钥", + "com_config_field_firecrawlApiKey": "Firecrawl API 密钥", + "com_config_field_firecrawlApiUrl": "Firecrawl API URL", + "com_config_field_firecrawlVersion": "Firecrawl 版本", + "com_config_field_jinaApiKey": "Jina API 密钥", + "com_config_field_jinaApiUrl": "Jina API URL", + "com_config_field_tavilyApiKey": "Tavily API 密钥", + "com_config_field_tavilySearchUrl": "Tavily 搜索 URL", + "com_config_field_cohereApiKey": "Cohere API 密钥", + "com_config_field_searchProvider": "搜索提供商", + "com_config_field_scraperProvider": "抓取器提供商", + "com_config_field_rerankerType": "重排序器类型", + "com_config_field_scraperTimeout": "抓取超时", + "com_config_field_safeSearch": "安全搜索", + "com_config_field_firecrawlOptions": "Firecrawl 选项", + "com_config_field_includeTags": "包含标签", + "com_config_field_excludeTags": "排除标签", + "com_config_field_waitFor": "等待目标", + "com_config_field_maxAge": "最大时效", + "com_config_field_mobile": "移动端", + "com_config_field_skipTlsVerification": "跳过 TLS 验证", + "com_config_field_blockAds": "拦截广告", + "com_config_field_removeBase64Images": "移除 Base64 图片", + "com_config_field_parsePDF": "解析 PDF", + "com_config_field_storeInCache": "存入缓存", + "com_config_field_zeroDataRetention": "零数据保留", + "com_config_field_location": "位置", + "com_config_field_onlyMainContent": "仅正文内容", + "com_config_field_changeTrackingOptions": "变更跟踪选项", + "com_config_field_formats": "格式", + "com_config_field_modes": "模式", + "com_config_field_schema": "Schema", + "com_config_field_tag": "标签", + "com_config_field_validKeys": "有效键", + "com_config_field_tokenLimit": "Token 限制", + "com_config_field_charLimit": "字符限制", + "com_config_field_personalize": "个性化", + "com_config_field_messageWindowSize": "消息窗口大小", + "com_config_field_agent": "智能体", + "com_config_field_instructions": "指令", + "com_config_field_model_parameters": "模型参数", + "com_config_field_privacyPolicy": "隐私政策", + "com_config_field_termsOfService": "服务条款", + "com_config_field_customWelcome": "自定义欢迎语", + "com_config_field_endpointsMenu": "端点菜单", + "com_config_field_modelSelect": "模型选择", + "com_config_field_parameters": "参数", + "com_config_field_sidePanel": "侧边栏", + "com_config_field_multiConvo": "多会话", + "com_config_field_bookmarks": "书签", + "com_config_field_memories": "记忆", + "com_config_field_presets": "预设", + "com_config_field_prompts": "提示词", + "com_config_field_agents": "智能体", + "com_config_field_temporaryChat": "临时对话", + "com_config_field_temporaryChatRetention": "临时对话保留时长", + "com_config_field_runCode": "运行代码", + "com_config_field_fileSearch": "文件搜索", + "com_config_field_fileCitations": "文件引用", + "com_config_field_peoplePicker": "人员选择器", + "com_config_field_marketplace": "市场", + "com_config_field_externalUrl": "外部 URL", + "com_config_field_openNewTab": "在新标签页打开", + "com_config_field_modalAcceptance": "弹窗确认", + "com_config_field_modalTitle": "弹窗标题", + "com_config_field_modalContent": "弹窗内容", + "com_config_field_use": "使用", + "com_config_field_create": "创建", + "com_config_field_share": "共享", + "com_config_field_trustCheckbox": "信任复选框", + "com_config_field_subLabel": "子标签", + "com_config_field_users": "用户", + "com_config_field_groups": "群组", + "com_config_field_roles": "角色", + "com_config_field_siteKey": "站点密钥", + "com_config_field_size": "大小", + "com_config_field_avatar": "头像", + "com_config_field_image": "图片", + "com_config_field_document": "文档", + "com_config_field_socialLogins": "社交登录", + "com_config_field_allowedDomains": "允许的域名", + "com_config_field_startBalance": "初始余额", + "com_config_field_autoRefillEnabled": "自动补充已启用", + "com_config_field_refillIntervalValue": "补充间隔值", + "com_config_field_refillIntervalUnit": "补充间隔单位", + "com_config_field_refillAmount": "补充额度", + "com_config_field_tts": "文字转语音", + "com_config_field_stt": "语音转文字", + "com_config_field_speechTab": "语音标签页", + "com_config_field_openai": "OpenAI", + "com_config_field_azureOpenAI": "Azure OpenAI", + "com_config_field_elevenlabs": "ElevenLabs", + "com_config_field_localai": "LocalAI", + "com_config_field_voices": "音色", + "com_config_field_instanceName": "实例名称", + "com_config_field_deploymentName": "部署名称", + "com_config_field_apiVersion": "API 版本", + "com_config_field_websocketUrl": "WebSocket URL", + "com_config_field_voice_settings": "音色设置", + "com_config_field_similarity_boost": "相似度提升", + "com_config_field_stability": "稳定性", + "com_config_field_use_speaker_boost": "使用说话人增强", + "com_config_field_pronunciation_dictionary_locators": "发音词典定位器", + "com_config_field_backend": "后端", + "com_config_field_conversationMode": "对话模式", + "com_config_field_advancedMode": "高级模式", + "com_config_field_speechToText": "语音转文字", + "com_config_field_textToSpeech": "文字转语音", + "com_config_field_engineSTT": "语音识别引擎", + "com_config_field_languageSTT": "语音识别语言", + "com_config_field_autoTranscribeAudio": "自动转录音频", + "com_config_field_decibelValue": "分贝值", + "com_config_field_autoSendText": "自动发送文本", + "com_config_field_engineTTS": "语音合成引擎", + "com_config_field_voice": "音色", + "com_config_field_languageTTS": "语音合成语言", + "com_config_field_automaticPlayback": "自动播放", + "com_config_field_playbackRate": "播放速率", + "com_config_field_cacheTTS": "缓存语音合成", + "com_config_field_fileUploads": "文件上传", + "com_config_field_conversationsImport": "会话导入", + "com_config_field_ipMax": "IP 上限", + "com_config_field_ipWindowInMinutes": "IP 时间窗口(分钟)", + "com_config_field_userMax": "用户上限", + "com_config_field_userWindowInMinutes": "用户时间窗口(分钟)", + "com_config_field_serverFileSizeLimit": "服务器文件大小限制", + "com_config_field_avatarSizeLimit": "头像大小限制", + "com_config_field_fileTokenLimit": "文件 Token 限制", + "com_config_field_imageGeneration": "图片生成", + "com_config_field_clientImageResize": "客户端图片缩放", + "com_config_field_supportedMimeTypes": "支持的 MIME 类型", + "com_config_field_maxWidth": "最大宽度", + "com_config_field_maxHeight": "最大高度", + "com_config_field_percentage": "百分比", + "com_config_field_fileLimit": "文件数量限制", + "com_config_field_fileSizeLimit": "文件大小限制", + "com_config_field_totalSizeLimit": "总大小限制", + "com_config_field_px": "像素", + "com_config_field_text": "文本", + "com_config_field_enforce": "强制执行", + "com_config_field_prioritize": "优先", + "com_config_field_addedEndpoints": "已添加端点", + "com_config_field_preset": "预设", + "com_config_field_order": "顺序", + "com_config_field_group": "群组", + "com_config_field_groupIcon": "分组图标", + "com_config_field_showIconInMenu": "在菜单中显示图标", + "com_config_field_showIconInHeader": "在顶栏显示图标", + "com_config_field_iconURL": "图标 URL", + "com_config_field_authType": "认证类型", + "com_config_field_executeCode": "执行代码", + "com_config_field_all": "全部", + "com_config_field_openAI": "OpenAI", + "com_config_field_google": "Google", + "com_config_field_anthropic": "Anthropic", + "com_config_field_azureAssistants": "Azure 助手", + "com_config_field_assistants": "助手", + "com_config_field_custom": "自定义", + "com_config_field_gptPlugins": "插件", + "com_config_field_bedrock": "Bedrock", + "com_config_field_streamRate": "流式速率", + "com_config_field_titlePrompt": "标题提示词", + "com_config_field_titleModel": "标题模型", + "com_config_field_titleConvo": "对话标题生成", + "com_config_field_titleMethod": "标题生成方式", + "com_config_field_titleEndpoint": "标题生成端点", + "com_config_field_titlePromptTemplate": "标题提示词模板", + "com_config_field_vertex": "Vertex", + "com_config_field_projectId": "项目 ID", + "com_config_field_serviceKeyFile": "服务密钥文件", + "com_config_field_disableBuilder": "禁用构建器", + "com_config_field_pollIntervalMs": "轮询间隔(毫秒)", + "com_config_field_timeoutMs": "超时(毫秒)", + "com_config_field_supportedIds": "支持的 ID", + "com_config_field_excludedIds": "排除的 ID", + "com_config_field_privateAssistants": "私有助手", + "com_config_field_retrievalModels": "检索模型", + "com_config_field_capabilities": "功能", + "com_config_field_fetch": "获取", + "com_config_field_userIdQuery": "用户 ID 查询", + "com_config_field_recursionLimit": "递归限制", + "com_config_field_maxRecursionLimit": "最大递归限制", + "com_config_field_maxCitations": "最大引用数", + "com_config_field_maxCitationsPerFile": "每文件最大引用数", + "com_config_field_minRelevanceScore": "最小相关度评分", + "com_config_field_allowedProviders": "允许的提供商", + "com_config_field_summarize": "摘要", + "com_config_field_summaryModel": "摘要模型", + "com_config_field_forcePrompt": "强制提示词", + "com_config_field_modelDisplayLabel": "模型显示标签", + "com_config_field_addParams": "附加参数", + "com_config_field_dropParams": "移除参数", + "com_config_field_customParams": "自定义参数", + "com_config_field_customOrder": "自定义顺序", + "com_config_field_directEndpoint": "直连端点", + "com_config_field_titleMessageRole": "标题消息角色", + "com_config_field_defaultParamsEndpoint": "默认参数端点", + "com_config_field_paramDefinitions": "参数定义", + "com_config_field_serverless": "无服务器", + "com_config_field_additionalHeaders": "附加请求头", + "com_config_field_startup": "启动", + "com_config_field_iconPath": "图标路径", + "com_config_field_initTimeout": "初始化超时", + "com_config_field_chatMenu": "聊天菜单", + "com_config_field_serverInstructions": "服务器指令", + "com_config_field_requiresOAuth": "需要 OAuth", + "com_config_field_command": "命令", + "com_config_field_args": "参数", + "com_config_field_env": "环境变量", + "com_config_field_availableRegions": "可用区域", + "com_config_field_maxToolResultChars": "工具结果最大字符数", + "com_config_field_key": "键", + "com_config_field_source": "来源", + "com_config_field_customUserVars": "自定义用户变量", + "com_config_field_sseReadTimeout": "SSE 读取超时", + "com_config_field_custom_header": "自定义请求头", + "com_config_field_authorization_type": "授权类型", + "com_config_field_authorization_url": "授权 URL", + "com_config_field_token_url": "令牌 URL", + "com_config_field_client_id": "客户端 ID", + "com_config_field_client_secret": "客户端密钥", + "com_config_field_scope": "权限范围", + "com_config_field_redirect_uri": "重定向 URI", + "com_config_field_token_exchange_method": "令牌交换方法", + "com_config_field_grant_types_supported": "支持的授权类型", + "com_config_field_token_endpoint_auth_methods_supported": "令牌端点认证方法", + "com_config_field_response_types_supported": "支持的响应类型", + "com_config_field_code_challenge_methods_supported": "代码质询方法", + "com_config_field_skip_code_challenge_check": "跳过代码质询检查", + "com_config_field_revocation_endpoint": "吊销端点", + "com_config_field_revocation_endpoint_auth_methods_supported": "吊销端点认证方法", + "com_config_field_oauth_headers": "OAuth 请求头", + "com_config_field_reserveRatio": "预留比例", + "com_config_field_maxSummaryTokens": "最大摘要 Token 数", + "com_config_field_updatePrompt": "更新提示词", + "com_config_field_trigger": "触发条件", + "com_config_field_value": "值", + "com_config_field_contextPruning": "上下文裁剪", + "com_config_field_keepLastAssistants": "保留最近的助手消息", + "com_config_field_softTrimRatio": "软裁剪比例", + "com_config_field_hardClearRatio": "硬清除比例", + "com_config_field_minPrunableToolChars": "可裁剪工具消息最小字符数", + "com_config_field_list": "列表", + "com_config_field_endpoint": "端点", + "com_config_field_endpointType": "端点类型", + "com_config_field_isArchived": "已归档", + "com_config_field_user": "用户", + "com_config_field_messages": "消息", + "com_config_field_tools": "工具", + "com_config_field_modelLabel": "模型标签", + "com_config_field_userLabel": "用户标签", + "com_config_field_promptPrefix": "提示词前缀", + "com_config_field_temperature": "温度", + "com_config_field_topP": "Top P", + "com_config_field_topK": "Top K", + "com_config_field_top_p": "Top P", + "com_config_field_frequency_penalty": "频率惩罚", + "com_config_field_presence_penalty": "存在惩罚", + "com_config_field_parentMessageId": "父消息 ID", + "com_config_field_maxOutputTokens": "最大输出 Token 数", + "com_config_field_maxContextTokens": "最大上下文 Token 数", + "com_config_field_max_tokens": "最大 Token 数", + "com_config_field_promptCache": "提示词缓存", + "com_config_field_system": "系统设置", + "com_config_field_thinking": "深度思考", + "com_config_field_thinkingBudget": "思考预算", + "com_config_field_stream": "流式输出", + "com_config_field_artifacts": "Artifacts", + "com_config_field_context": "上下文", + "com_config_field_examples": "示例", + "com_config_field_input": "输入", + "com_config_field_content": "内容", + "com_config_field_output": "输出", + "com_config_field_tags": "标签", + "com_config_field_resendFiles": "重发文件", + "com_config_field_file_ids": "文件 ID", + "com_config_field_imageDetail": "图片细节", + "com_config_field_reasoning_effort": "推理投入", + "com_config_field_reasoning_summary": "推理摘要", + "com_config_field_verbosity": "详细程度", + "com_config_field_useResponsesApi": "使用 Responses API", + "com_config_field_web_search": "网络搜索", + "com_config_field_url_context": "URL 上下文", + "com_config_field_disableStreaming": "禁用流式输出", + "com_config_field_assistant_id": "助手 ID", + "com_config_field_agent_id": "智能体 ID", + "com_config_field_maxTokens": "最大 Token 数", + "com_config_field_additionalModelRequestFields": "附加模型请求字段", + "com_config_field_additional_instructions": "附加指令", + "com_config_field_append_current_datetime": "附加当前日期时间", + "com_config_field_presetOverride": "预设覆盖", + "com_config_field_stop": "停止序列", + "com_config_field_greeting": "问候语", + "com_config_field_spec": "规格", + "com_config_field_expiredAt": "过期时间", + "com_config_field_resendImages": "重发图片", + "com_config_field_chatGptLabel": "ChatGPT 标签", + "com_config_field_conversationId": "会话 ID", + "com_config_field_presetId": "预设 ID", + "com_config_field_defaultPreset": "默认预设", + "com_config_field_style": "风格", + "com_config_field_public": "公开", + "com_config_field_remoteAgents": "远程智能体", + "com_config_field_effort": "投入", + "com_config_field_inferenceProfiles": "推理配置", + "com_config_field_messages_item": "消息", + "com_config_field_tags_item": "标签", + "com_config_field_file_ids_item": "文件 ID", + "com_config_field_stop_item": "停止序列", + "com_config_field_pronunciation_dictionary_locators_item": "定位器", + "com_config_field_includedTools_item": "工具", + "com_config_field_filteredTools_item": "工具", + "com_config_field_defaultPinnedTools_item": "工具", + "com_config_field_validKeys_item": "键", + "com_config_field_allowedDomains_item": "域名", + "com_config_field_socialLogins_item": "登录方式", + "com_config_field_voices_item": "音色", + "com_config_field_formats_item": "格式", + "com_config_field_includeTags_item": "标签", + "com_config_field_excludeTags_item": "标签", + "com_config_field_languages_item": "语言", + "com_config_field_modes_item": "模式", + "com_config_field_summarization": "摘要", + "com_config_field_oauth": "OAuth", + "com_config_field_stderr": "标准错误", + "com_config_field_thinkingLevel": "思考等级", + "com_config_field_showLabel": "显示标签", + "com_config_field_showDefault": "显示默认值", + "com_config_field_range": "取值范围", + "com_config_field_min": "最小值", + "com_config_field_max": "最大值", + "com_config_field_step": "步长", + "com_config_field_enumMappings": "枚举映射", + "com_config_field_component": "组件", + "com_config_field_optionType": "选项类型", + "com_config_field_columnSpan": "跨列数", + "com_config_field_columns": "列", + "com_config_field_labelCode": "标签代码", + "com_config_field_placeholderCode": "占位符代码", + "com_config_field_descriptionCode": "描述代码", + "com_config_field_minText": "最小值文本", + "com_config_field_maxText": "最大值文本", + "com_config_field_minTags": "最少标签数", + "com_config_field_maxTags": "最多标签数", + "com_config_field_includeInput": "包含输入", + "com_config_field_descriptionSide": "描述位置", + "com_config_field_searchPlaceholder": "搜索占位符", + "com_config_field_selectPlaceholder": "选择占位符", + "com_config_field_searchPlaceholderCode": "搜索占位符代码", + "com_config_field_selectPlaceholderCode": "选择占位符代码", + "com_config_field_grant_types_supported_item": "授权类型", + "com_config_field_token_endpoint_auth_methods_supported_item": "方法", + "com_config_field_response_types_supported_item": "响应类型", + "com_config_field_code_challenge_methods_supported_item": "方法", + "com_config_field_revocation_endpoint_auth_methods_supported_item": "方法", + "com_config_field_list_item": "条目", + "com_config_field_examples_item": "示例", + "com_config_field_groups_item": "群组", + "com_config_field_custom_item": "条目", + "com_config_field_paramDefinitions_item": "参数定义", + "com_config_field_options_item": "选项", + "com_config_field_dropParams_item": "参数", + "com_config_field_supportedIds_item": "ID", + "com_config_field_excludedIds_item": "ID", + "com_config_field_retrievalModels_item": "模型", + "com_config_field_models_item": "模型", + "com_config_field_allowedProviders_item": "提供商", + "com_config_field_addedEndpoints_item": "端点", + "com_config_field_supportedMimeTypes_item": "MIME 类型", + "com_config_field_args_item": "参数", + "com_config_field_availableRegions_item": "区域", + "com_config_field_mcpServers_item": "服务器", + "com_config_field_default_item": "条目", + "com_config_field_capabilities_item": "能力", + "com_config_field_tavilyExtractUrl": "Tavily 提取 URL", + "com_config_field_tavilySearchOptions": "Tavily 搜索选项", + "com_config_field_tavilyScraperOptions": "Tavily 抓取选项", + "com_config_field_searchDepth": "搜索深度", + "com_config_field_extractDepth": "提取深度", + "com_config_field_maxResults": "最大结果数", + "com_config_field_includeImages": "包含图片", + "com_config_field_includeImageDescriptions": "包含图片描述", + "com_config_field_includeFavicon": "包含网站图标", + "com_config_field_includeAnswer": "包含回答", + "com_config_field_includeRawContent": "包含原始内容", + "com_config_field_includeDomains": "包含域名", + "com_config_field_excludeDomains": "排除域名", + "com_config_field_topic": "主题", + "com_config_field_timeRange": "时间范围", + "com_config_field_chunksPerSource": "每来源分块数", + "com_config_field_format": "格式", + "com_config_field_allowedAddresses": "允许的地址", + "com_config_field_autoSubmitFromUrl": "从 URL 自动提交", + "com_config_field_skills": "技能", + "com_config_field_defaultActiveOnShare": "共享时默认启用", + "com_config_field_thinkingDisplay": "思考过程显示", + "com_config_field_cloudfront": "CloudFront", + "com_config_field_domain": "域名", + "com_config_field_distributionId": "分发 ID", + "com_config_field_invalidateOnDelete": "删除时失效缓存", + "com_config_field_imageSigning": "图片签名", + "com_config_field_urlExpiry": "URL 过期时间", + "com_config_field_cookieExpiry": "Cookie 过期时间", + "com_config_field_cookieDomain": "Cookie 域名", + "com_config_field_storageRegion": "存储区域", + "com_config_field_includeRegionInPath": "路径中包含区域", + "com_config_field_requireSignedAccess": "需要签名访问", + "com_config_field_remoteApi": "远程 API", + "com_config_field_auth": "认证", + "com_config_field_oidc": "OIDC", + "com_config_field_issuer": "签发者", + "com_config_field_audience": "受众", + "com_config_field_jwksUri": "JWKS URI", + "com_config_field_forward_audience_on_refresh": "刷新时转发受众", + "com_config_field_proxy": "代理", + "com_config_field_retentionMode": "保留模式", + "com_config_field_buildInfo": "构建信息", + "com_config_field_isTemporary": "是否临时", + "com_config_field_hideBadgeRow": "隐藏徽章行", + "com_config_field_guardrailConfig": "护栏", + "com_config_field_guardrailIdentifier": "护栏标识符", + "com_config_field_guardrailVersion": "护栏版本", + "com_config_field_trace": "追踪", + "com_config_field_streamProcessingMode": "流处理模式", + "com_config_field_allowedAddresses_item": "地址", + "com_config_field_includeDomains_item": "域名", + "com_config_field_excludeDomains_item": "域名", + "com_config_field_agent_ids": "智能体 ID", + "com_config_field_agent_ids_item": "智能体 ID", + "com_config_field_allowSelf": "允许自身", + "com_config_field_cacheRead": "缓存读取", + "com_config_field_cacheWrite": "缓存写入", + "com_config_field_code": "代码", + "com_config_field_completion": "补全", + "com_config_field_configureObo": "配置代表访问(OBO)", + "com_config_field_contextCost": "上下文成本", + "com_config_field_contextUsage": "上下文用量", + "com_config_field_conversation_starters": "对话开场白", + "com_config_field_conversation_starters_item": "开场白", + "com_config_field_currency": "货币", + "com_config_field_customPatterns": "自定义匹配模式", + "com_config_field_customPatterns_item": "匹配模式", + "com_config_field_github": "GitHub", + "com_config_field_intervalMinutes": "间隔(分钟)", + "com_config_field_maxCatalogSkills": "目录技能上限", + "com_config_field_maxInputTokens": "最大输入 Token 数", + "com_config_field_messageFilter": "消息过滤", + "com_config_field_obo": "代表访问(OBO)", + "com_config_field_pii": "个人身份信息", + "com_config_field_rate": "费率", + "com_config_field_reasoningFormat": "推理格式", + "com_config_field_reasoningKey": "推理键", + "com_config_field_includeReasoningContent": "包含推理内容", + "com_config_field_includeReasoningHistory": "包含推理历史", + "com_config_field_regex": "正则表达式", + "com_config_field_retainAgentFiles": "保留智能体文件", + "com_config_field_runOnStartup": "启动时运行", + "com_config_field_sensitive": "敏感", + "com_config_field_sharedLinks": "共享链接", + "com_config_field_showOnLanding": "在首页显示", + "com_config_field_skillSync": "技能同步", + "com_config_field_softDefault": "软默认", + "com_config_field_sources": "来源", + "com_config_field_sources_item": "来源", + "com_config_field_starterPatterns": "开场白匹配模式", + "com_config_field_starterPatterns_item": "匹配模式", + "com_config_field_subagents": "子智能体", + "com_config_field_titleTiming": "标题生成时机", + "com_config_field_tokenConfig": "Token 配置", + "com_config_section_fileStrategies": "文件策略", + "com_config_section_fileStrategies_desc": "为每个端点配置文件处理策略", + "com_config_section_cloudfront": "CloudFront", + "com_config_section_cloudfront_desc": "通过 Amazon CloudFront 分发提供文件", + "com_config_section_filteredTools": "排除的工具", + "com_config_section_filteredTools_desc": "被排除在可用范围之外的工具", + "com_config_section_imageOutputType": "图片输出类型", + "com_config_section_imageOutputType_desc": "生成图片的输出格式", + "com_config_section_includedTools": "包含的工具", + "com_config_section_includedTools_desc": "显式纳入可用范围的工具", + "com_config_section_messageFilter": "消息过滤", + "com_config_section_messageFilter_desc": "过滤或拦截用户消息中的匹配模式", + "com_config_section_langfuse": "Langfuse", + "com_config_section_langfuse_desc": "将此租户连接到 Langfuse 项目以导出追踪数据和反馈评分", + "com_config_langfuse_enabled": "Langfuse 连接", + "com_config_langfuse_description": "导出本组织内所有智能体的追踪数据和反馈评分。", + "com_config_langfuse_beta": "测试版", + "com_config_langfuse_destination": "目标", + "com_config_langfuse_select_destination": "选择目标", + "com_config_langfuse_public_key": "公钥", + "com_config_langfuse_secret_key": "密钥", + "com_config_langfuse_checking": "正在与 Langfuse 验证...", + "com_config_langfuse_save_and_enable": "保存并启用", + "com_config_langfuse_enable": "启用", + "com_config_langfuse_disable": "禁用", + "com_config_langfuse_verified": "已通过 Langfuse 验证", + "com_config_langfuse_not_configured": "未配置", + "com_config_langfuse_not_verified": "未验证", + "com_config_langfuse_test_fail": "无法连接到 Langfuse", + "com_config_langfuse_saved": "Langfuse 连接已保存", + "com_config_langfuse_tenant_wide": "Langfuse 连接为租户级设置,只能在基础配置中管理。", + "com_config_section_secureImageLinks": "安全图片链接", + "com_config_section_secureImageLinks_desc": "启用安全、需认证的图片 URL 分发", + "com_config_section_skillSync": "技能同步", + "com_config_section_skillSync_desc": "定期从外部来源拉取技能定义", + "com_config_section_summarization": "摘要", + "com_config_section_summarization_desc": "配置会话摘要行为", + "com_endpoint_prompt_cache": "提示词缓存", + "com_endpoint_anthropic_prompt_cache": "在 API 端缓存稳定的提示词上下文(系统消息、工具、长输入),以减少 Anthropic 模型每次请求的输入 Token 数", + "com_auth_title": "管理面板", + "com_auth_email_label": "邮箱", + "com_auth_email_placeholder": "admin@example.com", + "com_auth_password_label": "密码", + "com_auth_password_placeholder": "输入你的密码", + "com_auth_sign_in": "登录", + "com_auth_signing_in": "登录中...", + "com_auth_email_required": "邮箱为必填项", + "com_auth_email_invalid": "必须填写有效的邮箱地址", + "com_auth_password_required": "密码为必填项", + "com_auth_login_failed": "登录失败", + "com_auth_2fa_required": "需要进行双重认证", + "com_auth_2fa_title": "双重认证", + "com_auth_2fa_prompt": "请输入验证器应用中的 6 位验证码。", + "com_auth_2fa_code_label": "验证码", + "com_auth_2fa_code_placeholder": "000000", + "com_auth_2fa_verify": "验证", + "com_auth_2fa_verifying": "验证中...", + "com_auth_2fa_invalid_code": "验证码无效,请重试。", + "com_auth_2fa_expired": "会话已过期,请重新登录。", + "com_auth_2fa_back": "返回登录", + "com_auth_unable_connect": "无法连接,请重试。", + "com_auth_show_password": "显示密码", + "com_auth_hide_password": "隐藏密码", + "com_auth_sso_sign_in": "使用 SSO 登录", + "com_auth_sso_redirecting": "正在跳转...", + "com_auth_sso_completing": "正在完成登录...", + "com_auth_sso_error_title": "认证失败", + "com_auth_sso_no_code": "未收到授权码,请重试。", + "com_auth_sso_exchange_failed": "认证失败。授权码可能已过期。", + "com_auth_sso_back_to_login": "返回登录", + "com_auth_sso_redirecting_auto": "正在跳转到你的身份提供商...", + "com_auth_sso_redirect_failed": "SSO 跳转失败。你可以在下方手动登录。", + "com_error_page_title": "出了点问题", + "com_error_page_desc": "发生了意外错误。请重试或返回首页。", + "com_error_not_found_title": "页面未找到", + "com_error_not_found_desc": "你访问的页面不存在或已被移动。", + "com_scope_base_config": "基础配置", + "com_scope_base_config_desc": "来自 librechat.yaml 的默认设置", + "com_scope_search": "搜索角色和群组...", + "com_scope_no_results": "未找到作用域。", + "com_scope_priority": "优先级 {{priority}}", + "com_scope_profile_values": "{{count}} 项配置档案值", + "com_scope_one_profile_value": "1 项配置档案值", + "com_scope_no_profile_values": "无配置档案值", + "com_scope_members": "{{count}} 名成员", + "com_scope_select": "选择作用域", + "com_scope_roles": "角色", + "com_scope_groups": "群组", + "com_scope_users": "用户", + "com_scope_default": "默认", + "com_scope_active": "生效中", + "com_scope_inactive": "未激活", + "com_scope_editing_base": "正在编辑基础配置", + "com_scope_previewing": "正在显示 {{type}} 的配置档案值:{{name}}", + "com_scope_editing": "正在编辑 {{type}}:{{name}}", + "com_scope_back_to_base": "返回基础配置", + "com_scope_keyboard_navigate": "导航", + "com_scope_keyboard_select": "选择", + "com_scope_keyboard_close": "关闭", + "com_scope_add_profile_value": "添加配置档案值", + "com_scope_edit_profile_value": "编辑配置档案值", + "com_scope_remove_profile_value": "移除配置档案值", + "com_scope_cascade_title": "配置档案", + "com_scope_inherited": "继承", + "com_scope_profile_source": "{{type}} 配置档案", + "com_scope_field_profiles": "字段配置档案", + "com_scope_no_field_profiles": "此字段暂无配置档案", + "com_scope_add_for_scope": "为此作用域添加配置档案值", + "com_scope_changed_to": "作用域已切换为 {{name}}", + "com_scope_show_changed_only": "仅显示已修改的值", + "com_scope_confirm_remove": "移除此配置档案值?", + "com_scope_confirm_yes": "移除", + "com_scope_edit_value_title": "编辑配置档案值", + "com_scope_set_value_title": "设置配置档案值", + "com_scope_no_changed_in_tab": "此标签页没有已修改的字段", + "com_scope_create": "创建", + "com_scope_create_new": "创建配置", + "com_scope_creating": "创建中...", + "com_scope_create_error": "配置创建失败", + "com_scope_no_available_roles": "所有角色都已有配置", + "com_scope_no_available_groups": "所有群组都已有配置", + "com_scope_preview": "预览配置", + "com_scope_delete": "删除配置", + "com_scope_delete_confirm": "确定删除“{{name}}”的配置?这将移除所有配置档案覆盖值。", + "com_scope_deleting": "删除中...", + "com_nav_theme": "主题", + "com_nav_theme_system": "跟随系统", + "com_nav_theme_dark": "暗色", + "com_nav_theme_light": "亮色", + "com_ui_toggle_theme": "切换主题", + "com_ui_dark_theme_enabled": "已启用暗色主题", + "com_ui_light_theme_enabled": "已启用亮色主题", + "com_ui_system_theme_enabled": "已启用系统主题", + "com_ui_settings": "设置", + "com_settings_theme_desc": "选择你偏好的配色方案", + "com_cmdk_label": "命令菜单", + "com_cmdk_placeholder": "搜索命令、设置、导航...", + "com_cmdk_no_results": "未找到结果。", + "com_cmdk_group_navigation": "导航", + "com_cmdk_group_actions": "操作", + "com_cmdk_group_sections": "配置区块", + "com_cmdk_group_tabs": "标签页", + "com_cmdk_set_theme": "设置主题:{{theme}}", + "com_ui_all": "全部", + "com_ui_select_all": "全选", + "com_ui_actions": "操作", + "com_ui_of": "/", + "com_ui_edit": "编辑", + "com_ui_active": "活跃", + "com_ui_paused": "已暂停", + "com_users_title": "用户管理", + "com_users_subtitle": "管理 LibreChat 的用户、角色和权限", + "com_users_add": "添加用户", + "com_users_total": "用户总数", + "com_users_admins": "管理员", + "com_users_recent": "最近注册", + "com_users_list": "用户列表", + "com_users_search": "搜索用户...", + "com_users_role_filter": "按角色筛选", + "com_users_col_user": "用户", + "com_users_col_role": "角色", + "com_users_col_provider": "提供商", + "com_users_col_status": "状态", + "com_users_col_joined": "加入时间", + "com_users_verified": "已验证", + "com_users_pending": "待验证", + "com_users_empty": "未找到用户", + "com_users_showing": "显示", + "com_users_name_placeholder": "姓名", + "com_users_email_required": "邮箱为必填项", + "com_users_email_placeholder": "邮箱", + "com_users_role_label": "角色", + "com_users_delete_title": "删除用户", + "com_users_delete_desc": "确定要删除 {{name}} 吗?此操作无法撤销。", + "com_users_no_assignments": "未分配角色或群组", + "com_users_assign_role": "添加到角色...", + "com_users_assign_group": "添加到群组...", + "com_users_remove_role_title": "从角色移除", + "com_users_remove_role_desc": "确定将 {{user}} 从“{{name}}”角色中移除吗?", + "com_users_remove_group_title": "从群组移除", + "com_users_remove_group_desc": "确定将 {{user}} 从“{{name}}”群组中移除吗?", + "com_users_detail_title": "用户详情", + "com_users_roles_label": "角色", + "com_users_groups_label": "群组", + "com_users_no_roles": "未分配角色", + "com_users_no_groups": "未分配群组", + "com_users_all_roles_assigned": "所有角色均已分配", + "com_users_all_groups_assigned": "所有群组均已分配", + "com_users_profile_already_created": "用户配置档案已存在", + "com_users_view_details": "查看详情", + "com_users_add_profiles": "添加配置档案", + "com_users_add_profiles_title": "添加配置档案", + "com_users_user_profile": "{{name}} 的配置档案", + "com_users_create_user_profile": "为 {{name}} 创建配置档案", + "com_users_no_profiles": "未分配配置档案", + "com_users_delete_profile_title": "删除用户配置档案", + "com_users_delete_profile_desc": "确定删除 {{name}} 的配置档案吗?此操作无法撤销。", + "com_groups_title": "群组", + "com_groups_subtitle": "管理用于配置档案和访问控制的用户群组", + "com_groups_create": "创建群组", + "com_groups_total": "群组总数", + "com_groups_members": "成员", + "com_groups_profiles": "配置档案", + "com_groups_list": "群组列表", + "com_groups_search": "搜索群组...", + "com_groups_priority": "优先级", + "com_groups_empty": "未找到群组", + "com_access_title": "访问管理", + "com_access_subtitle": "管理群组、角色和成员权限", + "com_access_tab_groups": "群组", + "com_access_tab_roles": "角色", + "com_access_search_groups": "搜索群组...", + "com_access_search_roles": "搜索角色...", + "com_access_create_group": "创建群组", + "com_access_create_role": "创建角色", + "com_access_groups_empty": "未找到群组", + "com_access_roles_empty": "未找到角色", + "com_access_roles_error": "角色加载失败", + "com_access_permissions_load_error": "无法加载该角色的权限。", + "com_access_no_results": "没有匹配的结果", + "com_access_manage_members": "管理成员", + "com_access_delete_group_title": "删除群组", + "com_access_delete_group_desc": "确定要删除“{{name}}”吗?所有成员将被移除,配置档案将丢失。", + "com_access_delete_role_title": "删除角色", + "com_access_delete_role_desc": "确定要删除“{{name}}”吗?所有成员将被移除,配置档案将丢失。", + "com_access_save_order_title": "保存优先级顺序", + "com_access_save_order_desc": "此操作将更新所有条目的优先级顺序。确定吗?", + "com_access_reorder_hint": "拖动条目调整优先级。靠上的条目优先级更高。", + "com_access_reorder_discard": "放弃", + "com_access_reorder_save": "保存顺序", + "com_access_unsaved_changes": "未保存的更改", + "com_access_reorder_item": "第 {{position}} 位的条目", + "com_access_reorder_lifted": "已从第 {{position}} 位拿起条目", + "com_access_reorder_moved": "已移动到第 {{position}} 位({{direction}})", + "com_access_reorder_dropped": "已从第 {{from}} 位拖放到第 {{to}} 位", + "com_access_reorder_canceled": "已取消拖动,条目回到第 {{position}} 位", + "com_access_system_role": "系统", + "com_access_members_of": "{{name}} 的成员", + "com_access_remove_member_title": "移除成员", + "com_access_remove_member_desc": "确定要将 {{user}} 从“{{name}}”中移除吗?", + "com_access_remove_member": "移除", + "com_access_add_members_placeholder": "搜索要添加的用户...", + "com_access_no_users_found": "未找到用户", + "com_access_no_members": "暂无成员", + "com_access_member_count": "{{count}} 名成员", + "com_access_pending_additions": "正在添加 {{count}} 名成员", + "com_access_pending_removals": "正在移除 {{count}} 名成员", + "com_access_details_saved": "详情已保存", + "com_access_permissions_saved": "权限已保存", + "com_access_member_ops_failed_one": "{{count}} 项成员操作失败", + "com_access_member_ops_failed_other": "{{count}} 项成员操作失败", + "com_access_details_saved_permissions_failed": "详情已保存,但权限保存失败:{{error}}", + "com_access_name_required": "姓名为必填项", + "com_access_group_unavailable": "群组已不可用", + "com_access_role_unavailable": "角色已不可用", + "com_access_col_name": "名称", + "com_access_group_name_placeholder": "例如:工程部", + "com_access_group_desc_placeholder": "可选描述...", + "com_access_role_name_placeholder": "例如:内容审核员", + "com_access_role_desc_placeholder": "可选描述...", + "com_access_active": "活跃", + "com_access_paused": "已暂停", + "com_access_edit_group": "编辑群组", + "com_access_edit_role": "编辑角色", + "com_access_tab_details": "详情", + "com_access_tab_permissions": "权限", + "com_access_tab_members": "成员", + "com_access_save_role": "保存角色", + "com_perm_title": "权限", + "com_perm_features": "允许的功能", + "com_perm_desc_PROMPTS": "创建、共享和使用提示词模板", + "com_perm_desc_AGENTS": "创建、共享和使用自定义智能体", + "com_perm_desc_MEMORIES": "管理跨会话的持久记忆", + "com_perm_desc_MCP_SERVERS": "连接和管理 MCP 工具服务器", + "com_perm_desc_REMOTE_AGENTS": "连接和管理远程智能体端点", + "com_perm_desc_SKILLS": "创建、共享和使用智能体技能", + "com_perm_desc_SHARED_LINKS": "创建和分享会话共享链接", + "com_perm_desc_PEOPLE_PICKER": "控制用户、群组和角色的可见性", + "com_perm_type_BOOKMARKS": "书签", + "com_perm_type_PROMPTS": "提示词", + "com_perm_type_AGENTS": "智能体", + "com_perm_type_MEMORIES": "记忆", + "com_perm_type_MULTI_CONVO": "多会话", + "com_perm_type_TEMPORARY_CHAT": "临时对话", + "com_perm_type_RUN_CODE": "运行代码", + "com_perm_type_WEB_SEARCH": "网络搜索", + "com_perm_type_PEOPLE_PICKER": "人员选择器", + "com_perm_type_MARKETPLACE": "市场", + "com_perm_type_FILE_SEARCH": "文件搜索", + "com_perm_type_FILE_CITATIONS": "文件引用", + "com_perm_type_MCP_SERVERS": "MCP 服务器", + "com_perm_type_REMOTE_AGENTS": "远程智能体", + "com_perm_type_SKILLS": "技能", + "com_perm_type_SHARED_LINKS": "共享链接", + "com_perm_USE": "使用", + "com_perm_CREATE": "创建", + "com_perm_UPDATE": "更新", + "com_perm_READ": "读取", + "com_perm_READ_AUTHOR": "读取作者", + "com_perm_SHARE": "共享", + "com_perm_OPT_OUT": "选择退出", + "com_perm_VIEW_USERS": "查看用户", + "com_perm_VIEW_GROUPS": "查看群组", + "com_perm_VIEW_ROLES": "查看角色", + "com_perm_SHARE_PUBLIC": "公开共享", + "com_perm_CONFIGURE_OBO": "配置代表访问(OBO)", + "com_help_title": "帮助", + "com_help_subtitle": "文档、指南和支持资源", + "com_help_resources": "资源", + "com_help_docs_title": "文档", + "com_help_docs_desc": "配置和运行 LibreChat 的完整指南", + "com_help_api_title": "配置参考", + "com_help_api_desc": "librechat.yaml 和环境变量设置的详细参考", + "com_help_community_title": "社区", + "com_help_community_desc": "加入 GitHub 社区参与讨论和贡献", + "com_help_discord_title": "Discord", + "com_help_discord_desc": "在 Discord 上与社区交流并获取支持", + "com_help_support": "支持", + "com_help_support_text": "需要帮助?请联系你的系统管理员,或查阅 LibreChat 文档中的故障排除指南。", + "com_a11y_results_found": "找到{{count}}个结果", + "com_a11y_filter_changed": "筛选已更新,共 {{count}} 个结果", + "com_a11y_value_hidden": "{{key}} 的值已隐藏", + "com_a11y_value_revealed": "{{key}} 的值已显示", + "com_a11y_remove_role": "移除角色 {{name}}", + "com_a11y_remove_group": "移除群组 {{name}}", + "com_a11y_remove_user_profile": "移除用户配置档案", + "com_a11y_assigned_profiles": "已分配的配置档案", + "com_a11y_available_roles": "可分配角色", + "com_a11y_available_groups": "可分配群组", + "com_a11y_admin_panel": "管理面板", + "com_a11y_pagination": "分页", + "com_a11y_previous_page": "上一页", + "com_a11y_next_page": "下一页", + "com_a11y_page_n": "第 {{page}} 页", + "com_a11y_rename_entry": "重命名 {{name}}", + "com_a11y_remove_override": "移除 {{name}} 的覆盖值", + "com_a11y_reset_to_default": "将 {{name}} 重置为默认值", + "com_a11y_add_item": "添加 {{name}}", + "com_access_tab_capabilities": "能力", + "com_cap_title": "系统能力", + "com_cap_subtitle": "管理哪些主体持有系统级能力", + "com_cap_count": "{{count}} / {{total}}", + "com_cap_edit_title": "编辑 {{name}} 的能力", + "com_cap_implied_by": "由 {{cap}} 隐含", + "com_cap_grant_success": "能力已授予", + "com_cap_revoke_success": "能力已撤销", + "com_cap_empty": "未找到持有能力的主体", + "com_cap_type_filter": "主体类型筛选", + "com_cap_col_type": "类型", + "com_cap_col_name": "名称", + "com_cap_col_capabilities": "能力", + "com_cap_col_status": "状态", + "com_cap_cat_users": "用户", + "com_cap_cat_groups": "群组", + "com_cap_cat_roles": "角色", + "com_cap_cat_config": "配置", + "com_cap_cat_content": "内容", + "com_cap_cat_system": "系统", + "com_cap_access_admin": "管理面板访问", + "com_cap_read_users": "读取用户", + "com_cap_manage_users": "管理用户", + "com_cap_read_groups": "读取群组", + "com_cap_manage_groups": "管理群组", + "com_cap_read_roles": "读取角色", + "com_cap_manage_roles": "管理角色", + "com_cap_read_configs": "读取配置", + "com_cap_manage_configs": "管理配置", + "com_cap_assign_configs": "分配配置", + "com_cap_read_usage": "读取用量", + "com_cap_read_agents": "读取智能体", + "com_cap_manage_agents": "管理智能体", + "com_cap_manage_mcpservers": "管理 MCP 服务器", + "com_cap_read_prompts": "读取提示词", + "com_cap_manage_prompts": "管理提示词", + "com_cap_read_skills": "读取技能", + "com_cap_manage_skills": "管理技能", + "com_cap_read_sharedlinks": "读取共享链接", + "com_cap_manage_sharedlinks": "管理共享链接", + "com_cap_read_assistants": "读取助手", + "com_cap_manage_assistants": "管理助手", + "com_cap_read_audit_log": "读取审计日志", + "com_cap_desc_access_admin": "管理面板完整访问", + "com_cap_desc_read_users": "查看用户列表和配置档案", + "com_cap_desc_manage_users": "创建、编辑和删除用户", + "com_cap_desc_read_groups": "查看群组列表和成员", + "com_cap_desc_manage_groups": "创建、编辑和删除群组", + "com_cap_desc_read_roles": "查看角色列表和权限", + "com_cap_desc_manage_roles": "创建、编辑和删除角色", + "com_cap_desc_read_configs": "查看配置设置", + "com_cap_desc_manage_configs": "编辑配置设置", + "com_cap_desc_assign_configs": "分配配置档案", + "com_cap_desc_read_usage": "查看用量指标与分析", + "com_cap_desc_read_agents": "查看智能体配置", + "com_cap_desc_manage_agents": "创建、编辑和删除智能体", + "com_cap_desc_manage_mcpservers": "管理 MCP 服务器连接", + "com_cap_desc_read_prompts": "查看提示词库", + "com_cap_desc_manage_prompts": "创建、编辑和删除提示词", + "com_cap_desc_read_skills": "查看技能配置", + "com_cap_desc_manage_skills": "创建、编辑和删除技能", + "com_cap_desc_read_sharedlinks": "查看会话共享链接", + "com_cap_desc_manage_sharedlinks": "管理会话共享链接", + "com_cap_desc_read_assistants": "查看助手配置", + "com_cap_desc_manage_assistants": "创建、编辑和删除助手", + "com_cap_desc_read_audit_log": "查看和导出授权变更审计日志", + "com_access_denied_title": "拒绝访问", + "com_access_denied_description": "你没有查看此页面的权限。请联系管理员。", + "com_cap_no_permission": "你需要 {{cap}} 权限才能执行此操作", + "com_cap_principal_unavailable": "主体已不可用", + "com_a11y_cap_filter_changed": "显示 {{count}} 个主体", + "com_nav_audit_log": "审计日志", + "com_audit_title": "审计日志", + "com_audit_subtitle": "跟踪所有系统能力变更", + "com_audit_col_timestamp": "时间戳", + "com_audit_col_actor": "操作者", + "com_audit_col_action": "操作", + "com_audit_col_target": "目标", + "com_audit_col_capability": "能力", + "com_audit_action_assigned": "已授予", + "com_audit_action_removed": "已撤销", + "com_audit_empty": "未找到审计日志条目", + "com_audit_entry_count_zero": "暂无条目", + "com_audit_entry_count_one": "{{count}} 条记录", + "com_audit_entry_count_other": "{{count}} 条记录", + "com_audit_date_from": "起始日期", + "com_audit_date_to": "结束日期", + "com_audit_filter_action_label": "按操作筛选", + "com_audit_search_label": "搜索审计日志", + "com_audit_filter_actor_id": "操作者", + "com_audit_filter_target_id": "目标", + "com_audit_filter_target_type": "目标类型", + "com_audit_filter_capability": "能力", + "com_audit_export_server": "导出全部匹配项", + "com_a11y_audit_row_open": "打开审计日志条目", + "com_audit_error": "审计日志加载失败", + "com_audit_detail_title": "审计日志条目", + "com_audit_detail_summary_assigned": "{{actor}} 向 {{target}} 授予了 {{capability}}", + "com_audit_detail_summary_removed": "{{actor}} 从 {{target}} 撤销了 {{capability}}", + "com_audit_detail_actor": "操作者", + "com_audit_detail_target": "目标", + "com_audit_detail_capability": "能力", + "com_audit_detail_timestamp": "时间", + "com_audit_detail_entry_id": "条目 ID", + "com_audit_detail_before": "变更前", + "com_audit_detail_after": "变更后", + "com_audit_detail_no_changes": "未记录详细变更", + "com_audit_detail_copy_permalink": "复制链接", + "com_audit_detail_not_found": "未找到审计日志条目。它可能已被清除,或链接不正确。", + "com_audit_detail_load_error": "无法加载该审计日志条目。请求失败——请稍后重试。", + "com_audit_detail_close": "关闭", + "com_a11y_filters": "筛选", + "com_a11y_audit_filter_changed": "{{count}} 条审计日志记录匹配当前筛选条件", + "com_a11y_audit_export_failed": "审计日志导出失败", + "com_nav_grants": "授权", + "com_nav_expand_sidebar": "展开侧边栏", + "com_nav_collapse_sidebar": "折叠侧边栏", + "com_nav_dashboard": "仪表盘", + "com_dash_title": "欢迎!", + "com_dash_subtitle": "这里是管理 LibreChat 实例所需的一切。", + "com_dash_quick_links": "快速链接", + "com_dash_config_desc": "查看和管理实例配置设置。", + "com_dash_access_desc": "创建和管理群组、分配角色,并精细调整组织内成员的权限。", + "com_dash_grants_desc": "控制每个角色可访问的能力,从读取配置到管理用户。", + "com_dash_help_desc": "文档、社区资源和支持渠道链接,帮助你充分利用 LibreChat。", + "com_dash_nav_tips": "导航技巧", + "com_dash_tip_sidebar": "侧边栏可以到达每个页面:配置、访问管理、授权和帮助。展开可查看标签,折叠则仅显示图标。", + "com_dash_tip_cmdk": "命令菜单可以搜索并跳转到任意页面、配置区块或配置标签页,还可以在菜单中切换亮色、暗色和系统主题。", + "com_grants_title": "系统授权", + "com_grants_subtitle": "按角色管理系统级能力", + "com_grants_tab_management": "管理", + "com_grants_tab_audit_log": "审计日志", + "com_grants_no_capabilities": "无能力", + "com_grants_capability_count": "{{count}} 项能力", + "com_grants_assign_btn": "添加用户授权", + "com_grants_assign_title": "向用户授予能力", + "com_grants_assign_placeholder": "搜索用户...", + "com_grants_assign_hint": "角色和群组可直接在上表中编辑。", + "com_grants_assign_no_users": "未找到符合条件的用户", + "com_error_load_groups": "群组加载失败,请重试。", + "com_error_load_members": "成员加载失败,请重试。", + "com_perm_unavailable_title": "无法验证权限", + "com_perm_unavailable_desc": "权限服务暂时不可用。请重新加载页面重试。", + "com_ui_reload": "重新加载", + "com_config_pending_reset": "待重置", + "com_config_secret_replace": "替换", + "com_a11y_secret_configured": "{{name}} 已配置;值已隐藏", + "com_a11y_secret_replace": "替换 {{name}}", + "com_a11y_secret_cancel_replace": "取消替换 {{name}}", + "com_config_validation_more": "...还有 {{count}} 项", + "com_scope_delete_error": "配置删除失败", + "com_kv_type_string": "abc", + "com_kv_type_number": "123", + "com_kv_type_boolean": "T/F", + "com_kv_type_json": "{ }", + "com_a11y_logo_alt": "LibreChat 徽标" +} diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 18d99af2..c44fc078 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -80,7 +80,9 @@ function RootPending() { const localize = useLocalize(); return (
-
+ {/* SSR renders the default locale; the browser may resolve another one on + hydration, so suppress the expected text mismatch (same as ). */} +
{localize('com_ui_loading')}
From 140d0797aa7a2a87ceb506bbc40eea4824f5d5b6 Mon Sep 17 00:00:00 2001 From: swakinx Date: Thu, 24 Sep 2026 21:55:57 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=8C=90=20feat:=20Add=20language=20set?= =?UTF-8?q?ting=20to=20settings=20dialog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add a language row with a Select dropdown (English / 中文(简体)) below the theme row, reusing the existing click-ui Select component - Persist the choice via i18nextLng (the detection cache key) and keep document.documentElement.lang in sync --- src/components/SettingsDialog.tsx | 40 +++++++++++++++++++++++++++- src/locales/en/translation.json | 5 +++- src/locales/zh-Hans/translation.json | 5 +++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/components/SettingsDialog.tsx b/src/components/SettingsDialog.tsx index e14d01dc..f464ba51 100644 --- a/src/components/SettingsDialog.tsx +++ b/src/components/SettingsDialog.tsx @@ -1,4 +1,5 @@ -import { Dialog } from '@clickhouse/click-ui'; +import { Dialog, Select } from '@clickhouse/click-ui'; +import { useTranslation } from 'react-i18next'; import type * as t from '@/types'; import { useTheme } from '@/contexts/ThemeContext'; import { useLocalize } from '@/hooks'; @@ -11,9 +12,26 @@ const THEME_LABEL_KEYS: Record = { dark: 'com_nav_theme_dark', }; +const LANGUAGE_OPTIONS = ['en', 'zh-Hans'] as const; +type LanguageOption = (typeof LANGUAGE_OPTIONS)[number]; +const LANGUAGE_LABEL_KEYS: Record = { + en: 'com_ui_language_english', + 'zh-Hans': 'com_ui_language_zh_hans', +}; + export function SettingsDialog({ open, onClose }: t.SettingsDialogProps) { const localize = useLocalize(); const { theme, setTheme } = useTheme(); + const { i18n } = useTranslation(); + + const resolvedLanguage = i18n.resolvedLanguage ?? i18n.language ?? 'en'; + const currentLanguage: LanguageOption = resolvedLanguage.startsWith('zh') ? 'zh-Hans' : 'en'; + + const setLanguage = (language: LanguageOption) => { + i18n.changeLanguage(language); + localStorage.setItem('i18nextLng', language); + document.documentElement.lang = language; + }; return (
+
+
+ + {localize('com_ui_language')} + +
+
+ +
+
diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index e3922958..7999b429 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -1247,5 +1247,8 @@ "com_kv_type_number": "123", "com_kv_type_boolean": "T/F", "com_kv_type_json": "{ }", - "com_a11y_logo_alt": "LibreChat logo" + "com_a11y_logo_alt": "LibreChat logo", + "com_ui_language": "Language", + "com_ui_language_english": "English", + "com_ui_language_zh_hans": "中文(简体)" } diff --git a/src/locales/zh-Hans/translation.json b/src/locales/zh-Hans/translation.json index 963560b4..376e4745 100644 --- a/src/locales/zh-Hans/translation.json +++ b/src/locales/zh-Hans/translation.json @@ -1234,5 +1234,8 @@ "com_kv_type_number": "123", "com_kv_type_boolean": "T/F", "com_kv_type_json": "{ }", - "com_a11y_logo_alt": "LibreChat 徽标" + "com_a11y_logo_alt": "LibreChat 徽标", + "com_ui_language": "语言", + "com_ui_language_english": "English", + "com_ui_language_zh_hans": "中文(简体)" } From 119a731b7d5d857cc64621a11ff9c696855d5c67 Mon Sep 17 00:00:00 2001 From: swakinx Date: Thu, 24 Sep 2026 21:56:06 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=90=9B=20fix:=20Localize=20role=20and?= =?UTF-8?q?=20target=20type=20dropdown=20options?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CreateUserDialog role select rendered raw SystemRoles values (USER/ADMIN); use localized labels instead - Audit log target-type filter rendered raw PrincipalType enum values; map them to localized labels --- src/components/grants/AuditLogTab.tsx | 7 ++++++- src/components/users/CreateUserDialog.tsx | 4 ++-- src/locales/en/translation.json | 7 ++++++- src/locales/zh-Hans/translation.json | 7 ++++++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/components/grants/AuditLogTab.tsx b/src/components/grants/AuditLogTab.tsx index ce2021e5..bf393cd7 100644 --- a/src/components/grants/AuditLogTab.tsx +++ b/src/components/grants/AuditLogTab.tsx @@ -41,6 +41,11 @@ const TARGET_TYPE_OPTIONS: readonly PrincipalType[] = [ PrincipalType.GROUP, PrincipalType.ROLE, ] as const; +const TARGET_TYPE_LABEL_KEYS: Record<(typeof TARGET_TYPE_OPTIONS)[number], string> = { + [PrincipalType.USER]: 'com_audit_target_user', + [PrincipalType.GROUP]: 'com_audit_target_group', + [PrincipalType.ROLE]: 'com_audit_target_role', +}; /** Radix `Select.Item` cannot use `value=""` (Radix reserves empty string for * "no selection"). Use a non-empty sentinel and translate to `''` in state. */ const TARGET_TYPE_ALL = '__all__'; @@ -510,7 +515,7 @@ export function AuditLogTab() { {localize('com_ui_all')} {TARGET_TYPE_OPTIONS.map((pt) => ( - {pt} + {localize(TARGET_TYPE_LABEL_KEYS[pt])} ))} diff --git a/src/components/users/CreateUserDialog.tsx b/src/components/users/CreateUserDialog.tsx index 9a2e79aa..0b776a90 100644 --- a/src/components/users/CreateUserDialog.tsx +++ b/src/components/users/CreateUserDialog.tsx @@ -97,8 +97,8 @@ export function CreateUserDialog({ open, onClose }: t.CreateUserDialogProps) { onChange={(e) => setRole(e.target.value as SystemRoles)} className="rounded-lg border border-(--cui-color-stroke-default) bg-(--cui-color-background-default) px-3 py-2 text-sm text-(--cui-color-text-default)" > - - + + diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 7999b429..433bce70 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -1250,5 +1250,10 @@ "com_a11y_logo_alt": "LibreChat logo", "com_ui_language": "Language", "com_ui_language_english": "English", - "com_ui_language_zh_hans": "中文(简体)" + "com_ui_language_zh_hans": "中文(简体)", + "com_audit_target_user": "User", + "com_audit_target_group": "Group", + "com_audit_target_role": "Role", + "com_users_role_admin": "Administrator", + "com_users_role_user": "User" } diff --git a/src/locales/zh-Hans/translation.json b/src/locales/zh-Hans/translation.json index 376e4745..01024f71 100644 --- a/src/locales/zh-Hans/translation.json +++ b/src/locales/zh-Hans/translation.json @@ -1237,5 +1237,10 @@ "com_a11y_logo_alt": "LibreChat 徽标", "com_ui_language": "语言", "com_ui_language_english": "English", - "com_ui_language_zh_hans": "中文(简体)" + "com_ui_language_zh_hans": "中文(简体)", + "com_audit_target_user": "用户", + "com_audit_target_group": "群组", + "com_audit_target_role": "角色", + "com_users_role_admin": "管理员", + "com_users_role_user": "用户" }