6d658b4f4d
- 工具系统从 kilostar/plugin/tool_plugin/ 迁移到 data/toolset/(manifest.json 声明式) - 新增 plugin_runtime 模块:BaseOrganization / GlobalPluginManager / loader / tool_bridge - 新增 org_task + org_task_event 表及 DAO(alembic 0009) - 新增 /api/v1/plugin 路由(submit/status/stream/install/reload) - 新增 data/plugin/example_dept 示例重型插件 - regulatory_node 支持聊天历史上下文注入 - send_file 改为 artifact 存盘 + SSE 推送下载链接 - 前端 WorkflowFileCard 组件 + ToolSettings README 渲染 - utils 整理:合并 access/role_check、standalone_proxy→ray_compat、删除废弃模块 - 项目结构文档移至 docs/STRUCTURE.md 并详细展开 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
96 lines
3.5 KiB
Python
96 lines
3.5 KiB
Python
# Copyright 2026 zhaoxi826
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""KiloStar 轻量级国际化工具。
|
|
|
|
设计原则:
|
|
- 纯内存字典,无文件 IO,Ray 远程序列化零成本。
|
|
- 支持环境变量 ``KILOSTAR_LANG`` 作为全局默认语言。
|
|
- API 层通过请求头 ``Accept-Language`` 解析首选语言。
|
|
|
|
当前支持:``zh`` (简体中文), ``en`` (English)。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Dict
|
|
|
|
from kilostar.utils.settings import get_settings
|
|
|
|
_DEFAULT_LOCALE: str = get_settings().kilostar_lang
|
|
|
|
# ─── API / 通用消息 ────────────────────────────────────────────────────────
|
|
|
|
_MESSAGES: Dict[str, Dict[str, str]] = {
|
|
"internal_error": {
|
|
"zh": "服务内部错误,请稍后重试",
|
|
"en": "Internal server error, please try again later.",
|
|
},
|
|
"user_not_found": {
|
|
"zh": "用户不存在或已被删除,请重新登录",
|
|
"en": "User does not exist or has been deleted. Please log in again.",
|
|
},
|
|
"provider_not_registered": {
|
|
"zh": "Provider {provider_title} 未注册",
|
|
"en": "Provider {provider_title} is not registered.",
|
|
},
|
|
"model_not_exist": {
|
|
"zh": "模型不存在",
|
|
"en": "Model does not exist.",
|
|
},
|
|
"api_not_found": {
|
|
"zh": "API endpoint not found",
|
|
"en": "API endpoint not found",
|
|
},
|
|
"frontend_not_found": {
|
|
"zh": "Frontend build not found",
|
|
"en": "Frontend build not found",
|
|
},
|
|
}
|
|
|
|
# ─── 工具函数 ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
def _resolve_locale(locale: str | None = None, accept_language: str | None = None) -> str:
|
|
"""确定最终使用的 locale。
|
|
|
|
优先级:显式传入 > Accept-Language 头 > KILOSTAR_LANG 环境变量 > 默认 zh。
|
|
"""
|
|
if locale:
|
|
return locale if locale in ("zh", "en") else _DEFAULT_LOCALE
|
|
if accept_language:
|
|
first = accept_language.split(",")[0].split(";")[0].strip().lower()
|
|
if "zh" in first:
|
|
return "zh"
|
|
if "en" in first:
|
|
return "en"
|
|
return _DEFAULT_LOCALE
|
|
|
|
|
|
def t(key: str, locale: str | None = None, accept_language: str | None = None, **kwargs) -> str:
|
|
"""通用消息翻译。
|
|
|
|
Args:
|
|
key: 消息键,如 ``internal_error``。
|
|
locale: 显式指定语言代码(``zh`` / ``en``)。
|
|
accept_language: 前端传来的 ``Accept-Language`` 头内容。
|
|
**kwargs: 模板变量插值。
|
|
|
|
Returns:
|
|
翻译后的字符串;若 key 不存在则返回 key 本身。
|
|
"""
|
|
loc = _resolve_locale(locale, accept_language)
|
|
text = _MESSAGES.get(loc, {}).get(key) or _MESSAGES.get(_DEFAULT_LOCALE, {}).get(key) or key
|
|
return text.format(**kwargs) if kwargs else text
|