Hy3test / i18n.py
ericsqin's picture
add hy3
ad51766
Raw
History Blame Contribute Delete
8.38 kB
"""Tiny dictionary-based i18n helper.
Selects the active language from ``HY_LANG`` env var (falls back to ``LANG`` /
``LC_ALL``). Anything starting with ``zh`` resolves to Simplified Chinese,
everything else to English.
Usage::
from i18n import t
label = t("send") # -> "Send" or "发送"
msg = t("warn.empty_msg") # nested-dotted keys
"""
from __future__ import annotations
import logging
import os
from typing import Any
logger = logging.getLogger(__name__)
DEFAULT_LANG = "en"
SUPPORTED_LANGS = ("en", "zh")
def _detect_lang() -> str:
raw = (
os.environ.get("HY_LANG")
or os.environ.get("LC_ALL")
or os.environ.get("LANG")
or DEFAULT_LANG
)
raw = raw.strip().lower()
if raw.startswith("zh"):
return "zh"
if raw[:2] in SUPPORTED_LANGS:
return raw[:2]
return DEFAULT_LANG
LANG = _detect_lang()
# ─── Dictionary ────────────────────────────────────────────────────────────
# Keys are flat dotted strings to keep lookup simple. Add new keys below in
# alphabetical groups for readability.
TRANSLATIONS: dict[str, dict[str, str]] = {
"en": {
# App chrome
"title": "Hy3 Chat Demo",
"title.notice_html": (
"The current demo version is offline; full-featured capabilities "
"will be available on the Tencent HY official website."
),
"examples_heading": "What can I help you with?",
"msg_placeholder": "Type a message...",
# Sidebar
"sidebar.think_level": "Think level",
"sidebar.think_level.info": "Control reasoning depth",
"sidebar.system_prompt": "System prompt",
"sidebar.system_prompt.placeholder": "You are a helpful AI assistant...",
"sidebar.temperature": "Temperature",
"sidebar.temperature.info": "Higher values produce more random outputs",
"sidebar.temperature.use_default": "Use model default",
"sidebar.max_tokens": "Max output tokens",
"sidebar.max_tokens.info": "Maximum tokens per response. Set to 0 to use the model's default.",
"sidebar.top_p": "Top P",
"sidebar.top_p.info": "Nucleus sampling probability threshold. Set to 0 to use the model's default.",
"sidebar.preserved_thinking": "Preserved thinking",
"sidebar.preserved_thinking.info": "When enabled, the model can retain reasoning content from previous assistant turns in the context, helping maintain reasoning continuity and conversation integrity while improving model performance.",
"sidebar.preserved_thinking.use_default": "Preserved thinking-Use model default",
"sidebar.preserved_thinking.use_default.info": "We recommend using \"Use model default\", which automatically enables this option for tool call workflows and disables it for pure text conversations.",
"sidebar.functions": "🔧 Functions",
"sidebar.functions.label": "Function definitions (JSON array)",
"sidebar.validate_btn": "Validate & Format",
# Tool area
"tool.result_label": "Function result",
"tool.result_placeholder": "Enter function return value... (Enter to submit)",
"tool.submit": "Submit",
"tool.call_header": "Function call ({i}/{n})",
"tool.call_label": "🔧 Call function",
# Display
"display.thinking": "Thinking...",
"display.thinking_done": "Thinking complete",
"display.code_copy": "Copy",
"display.code_copied": "Copied",
# Warnings / info
"warn.empty_msg": "Please enter a message",
"warn.invalid_fn_json": "Invalid function JSON, please fix or clear before sending: {err}",
"warn.request_failed": "Request failed, please retry or adjust parameters",
"warn.model_busy": "Model is still responding. Please wait for it to finish before sending a new message.",
"info.new_chat": "Start a new chat",
"warn.fn.enter_json": "Please enter function definition JSON",
"warn.fn.invalid_format": "Invalid JSON format: {err}",
"warn.fn.must_be_array": "JSON must be an array [...] or a single object {{...}}",
"warn.fn.item_not_object": "Item {i} is not a JSON object",
"warn.fn.item_invalid": "Item {i} has invalid format, expected {{type, function}} or {{name, parameters}}",
"warn.fn.duplicate_name": "Duplicate function name '{name}'",
"info.fn.validation_passed": "Validation passed, {n} function(s): {names}",
},
"zh": {
"title": "Hy3 Chat Demo",
"title.notice_html": (
"The current demo version is offline; full-featured capabilities "
"will be available on the Tencent HY official website."
),
"examples_heading": "今天我能帮你做点什么?",
"msg_placeholder": "输入消息...",
"sidebar.think_level": "思考等级",
"sidebar.think_level.info": "控制模型推理深度",
"sidebar.system_prompt": "系统提示词",
"sidebar.system_prompt.placeholder": "你是一个有帮助的 AI 助手...",
"sidebar.temperature": "Temperature",
"sidebar.temperature.info": "数值越高,回复越随机",
"sidebar.temperature.use_default": "Use model default",
"sidebar.max_tokens": "最大输出 Tokens",
"sidebar.max_tokens.info": "单次回复的最大 token 数。Set to 0 to use the model's default.",
"sidebar.top_p": "Top P",
"sidebar.top_p.info": "核采样概率阈值。Set to 0 to use the model's default.",
"sidebar.preserved_thinking": "Preserved thinking",
"sidebar.preserved_thinking.info": "是否在上下文中保留模型的思考过程。",
"sidebar.preserved_thinking.use_default": "Preserved thinking-Use model default",
"sidebar.preserved_thinking.use_default.info": "We recommend using \"Use model default\", which automatically enables this option for tool call workflows and disables it for pure text conversations.",
"sidebar.functions": "🔧 函数",
"sidebar.functions.label": "函数定义(JSON 数组)",
"sidebar.validate_btn": "校验 & 格式化",
"tool.result_label": "函数返回值",
"tool.result_placeholder": "请输入函数返回值...(回车提交)",
"tool.submit": "提交",
"tool.call_header": "函数调用 ({i}/{n})",
"tool.call_label": "🔧 调用函数",
"display.thinking": "思考中...",
"display.thinking_done": "已思考",
"display.code_copy": "复制",
"display.code_copied": "已复制",
"warn.empty_msg": "请输入消息内容",
"warn.invalid_fn_json": "函数 JSON 不合法,请先修正或清空: {err}",
"warn.request_failed": "请求失败,请重试或调整参数",
# Intentionally English for both locales: the warning should always
# appear in English regardless of the UI language.
"warn.model_busy": "Model is still responding. Please wait for it to finish before sending a new message.",
"info.new_chat": "已开启新会话",
"warn.fn.enter_json": "请输入函数定义 JSON",
"warn.fn.invalid_format": "JSON 格式错误: {err}",
"warn.fn.must_be_array": "JSON 必须是数组 [...] 或单个对象 {{...}}",
"warn.fn.item_not_object": "第 {i} 项不是 JSON 对象",
"warn.fn.item_invalid": "第 {i} 项格式不合法,期望 {{type, function}} 或 {{name, parameters}}",
"warn.fn.duplicate_name": "函数名 '{name}' 重复",
"info.fn.validation_passed": "校验通过,共 {n} 个函数: {names}",
},
}
def t(key: str, /, **fmt: Any) -> str:
"""Translate ``key`` for the active language with optional formatting."""
table = TRANSLATIONS.get(LANG, TRANSLATIONS[DEFAULT_LANG])
template = table.get(key) or TRANSLATIONS[DEFAULT_LANG].get(key)
if template is None:
logger.warning("missing i18n key: %s", key)
return key
if not fmt:
return template
try:
return template.format(**fmt)
except (KeyError, IndexError):
logger.warning("i18n format failure for key=%s args=%r", key, fmt)
return template