Files
mqttx/gpui-app/locales/en.yml
T
JoeAllen 05b37a8997 refactor: 按 gpui-kit 官方指南对齐(locales 拆分/render 无突变/动作统一)
skill 安装:npx skills add 因网络不可用,改为 gh-proxy 镜像克隆仓库后
手动覆盖 ~/.agents/skills 与 ~/.zcode/skills 两处安装(与官方最新一致)。

语言包按语言分文件(用户要求):
- locales/ui.yml(合并格式)→ locales/en.yml + locales/zh-CN.yml
  (rust-i18n 以文件名 stem 识别 locale,扁平 "ns.key": "value")
- i18n.rs 测试适配双文件:键集合一致性 + 占位符两侧一致强制保留

对齐 coding-guides / design-guides / auto-update:
- render 无突变:分组过滤悬空复位从 render 移到 delete_connection/
  save_connection 的 action 路径(normalize_group_filter)
- 消除 UI 层 hsla 字面量:消息色条改 when_some 条件上色;色板描边
  从白 60% 改主题底色(双主题下均为「与背景的缝隙」语义)
- 动作统一:标题栏菜单的资源监控/导出/导入/设置改 dispatch_action,
  与快捷键共享同一 Action(菜单/快捷键单一命令策略)
- auto-update 对齐官方指南:自动检查加 24h 节流(.last-update-check
  时间戳),手动检查更新不受限

保留(记录豁免理由):
- 手写 collapsible_section:官方 Accordion 非受控(内部索引状态),
  替代会丢「已配置默认展开」的受控行为
- 自研 update/:官方无内置 updater,指南推荐 self_update+应用自有
  状态机,现有实现(状态机/后台 worker/sha256/consent/原子替换)
  已符合该精神;换 self_update 反而放弃已有代理兜底与 7z 通道
- px() 几何常量:对话框/面板宽度与色点尺寸属文档化几何豁免,
  机械换算会引入视觉回归;min 约束的 px(0.) 为布局断言

42 测试全绿,实机冒烟通过。
2026-10-12 15:11:48 +08:00

348 lines
16 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MQTTX en 文案(rust-i18n:文件名即 locale,扁平 key: value)。
# key = 语义标识符 ns.name;en/zh-CN 两文件键集合必须一致——单测强制。
"aliyun.access_key_id": "AccessKey ID"
"aliyun.access_key_secret": "AccessKey Secret"
"aliyun.auth_mode": "Auth mode"
"aliyun.auth_token_mode": "Group token"
"aliyun.auth_triple_mode": "Per-device secret"
"aliyun.build_failed": "Failed to build connection: {e}"
"aliyun.device_id": "Device ID"
"aliyun.device_secret": "DeviceSecret (per-device)"
"aliyun.device_secret_ph": "Triple: DeviceSecret"
"aliyun.generate_connect": "Generate & connect"
"aliyun.group": "Group (optional)"
"aliyun.group_id": "Group ID"
"aliyun.help": "Token mode (Alibaba Cloud MQTT): endpoint {实例ID}.mqtt.aliyuncs.com, clientId={GroupId}@@@{设备ID}, password is the HMAC-SHA1 signature. Per-device secret (IoT Platform): endpoint {ProductKey}.iot-as-mqtt.{地域}.aliyuncs.com, signed per the official triple spec."
"aliyun.instance_id": "Instance ID"
"aliyun.preset_name": "Preset name"
"aliyun.product_key": "ProductKey (per-device)"
"aliyun.product_key_ph": "Triple: ProductKey"
"aliyun.region": "Region"
"aliyun.region_ph": "e.g. cn-shanghai (optional)"
"aliyun.save_preset": "Save preset"
"aliyun.saved_presets": "Saved presets"
"aliyun.title": "Alibaba Cloud IoT"
"color.blue": "Blue"
"color.cyan": "Cyan"
"color.green": "Green"
"color.indigo": "Indigo"
"color.magenta": "Magenta"
"color.orange": "Orange"
"color.purple": "Purple"
"color.red": "Red"
"color.rose": "Rose"
"color.yellow": "Yellow"
"common.advanced": "Advanced"
"common.all": "All"
"common.auto": "Auto"
"common.browse": "Browse…"
"common.cancel": "Cancel"
"common.clear": "Clear"
"common.close": "Close"
"common.collapse": "Collapse"
"common.delete": "Delete"
"common.edit": "Edit"
"common.new": "New"
"common.pause": "Pause"
"common.resume": "Resume"
"common.retry": "Retry"
"common.save": "Save"
"common.send": "Send"
"common.text": "Text"
"common.update": "Update"
"connview.logs": "Logs"
"connview.messages": "Messages"
"connview.subscriptions": "Subscriptions"
"dir.published": "Published"
"dir.received": "Received"
"encode.base64_failed": "Base64 decode failed: {e}"
"encode.hex_failed": "Hex decode failed: {e}"
"encode.hex_invalid": "Hex decode failed: non-hex character present"
"encode.hex_odd": "Hex length must be even (two chars per byte)"
"form.auth_section": "Auth & Keep-alive"
"form.auto_connect": "Connect on app start"
"form.auto_reconnect": "Auto reconnect on disconnect"
"form.auto_resub": "Auto-resubscribe on connect"
"form.basics": "Basics"
"form.cert_pair_required": "Client certificate and key must be provided together"
"form.clean_start": "Clean Start / Clean Session"
"form.client_id": "Client ID"
"form.client_id_required": "Client ID cannot be empty"
"form.conn_timeout": "Connect timeout (s)"
"form.conn_timeout_invalid": "Connect timeout must be an integer 1-65535 (seconds)"
"form.content_type_ph": "Content type (optional)"
"form.err_positive": "must be > 0 (0 is an MQTT 5 protocol error)"
"form.err_range": "must be an integer 0-65535"
"form.err_uint": "must be a non-negative integer"
"form.group": "Group"
"form.host": "Host"
"form.host_required": "Host cannot be empty"
"form.keep_alive": "Keep Alive (s)"
"form.keep_alive_short": "Keep Alive"
"form.max_packet": "Maximum Packet Size"
"form.max_reconnects": "Max reconnects (0 = unlimited)"
"form.max_reconnects_invalid": "Max reconnects must be a non-negative integer (0 = unlimited)"
"form.max_reconnects_ph": "0 = unlimited"
"form.name": "Name"
"form.name_ph": "Connection name"
"form.name_required": "Connection name cannot be empty"
"form.new_group": "New group"
"form.new_group_hint": "Overrides the selected group when filled"
"form.no_group": "No group"
"form.password": "Password"
"form.password_ph": "Password (optional)"
"form.path_missing": "{label}: path not found: {p}"
"form.port": "Port"
"form.port_invalid": "Port must be an integer 1-65535"
"form.protocol": "Protocol"
"form.receive_max": "Receive Maximum"
"form.receive_max_invalid": "Receive Maximum cannot exceed 65535"
"form.receive_max_ph": "Server receive maximum"
"form.receive_max_short": "Receive Maximum"
"form.regen_client_id": "Regenerate Client ID"
"form.response_topic_ph": "Response topic (optional)"
"form.saved_reconnect": "Saved. Takes effect after reconnect"
"form.session_expiry": "Session expiry (s)"
"form.session_expiry_invalid": "Session expiry must be a non-negative integer (0 = session ends with connection)"
"form.session_expiry_ph": "seconds (0 = session ends with connection)"
"form.test": "Test Connection"
"form.test_ok": "Connection test succeeded"
"form.testing": "Testing…"
"form.timeout_ph": "seconds (default 10)"
"form.title": "Connection Settings"
"form.topic_alias": "Topic Alias"
"form.topic_alias_invalid": "Topic Alias Maximum cannot exceed 65535"
"form.topic_alias_max": "Topic Alias Maximum"
"form.transport": "Transport"
"form.username": "Username"
"form.username_ph": "Username (optional)"
"form.will_content_type": "Content Type"
"form.will_enable": "Enable last will"
"form.will_payload": "Will payload"
"form.will_payload_ph": "Will message"
"form.will_response_topic": "Response Topic"
"form.will_section": "Last Will"
"form.will_topic": "Will topic"
"form.ws_path": "WS Path"
"form.ws_path_required": "WS path is required for WS/WSS transport"
"io.err_item_id": "Item {n}: id must not be empty"
"io.err_item_invalid": "Item {n} is not a valid connection: {e}"
"io.err_missing_field": "JSON object lacks the \"connections\" array"
"io.err_parse_json": "Failed to parse JSON: {e}"
"io.err_parse_json_path": "Failed to parse {p}"
"io.err_read": "Failed to read {p}: {e}"
"io.err_serialize": "Failed to serialize connections: {e}"
"io.err_utf8": "{p} is not valid UTF-8"
"io.err_write": "Failed to write {p}: {e}"
"io.exported": "Exported {n} connections to {path}"
"io.imported": "Imported {n}, skipped {n2}"
"kv.add": "Add property"
"msg.binary_hint": " (binary — switch to Hex in details)"
"msg.clear_confirm": "Clear all messages of this connection? This cannot be undone."
"msg.clear_sub_filter": "Clear subscription filter"
"msg.clear_title": "Clear Messages"
"msg.clear_tooltip": "Clear messages of this connection"
"msg.copy_details": "Copy full details (incl. MQTT 5 props)"
"msg.copy_payload": "Copy raw payload"
"msg.copy_topic": "Copy topic"
"msg.count": "{n} msgs"
"msg.details": "Details"
"msg.details_copied": "Details copied"
"msg.empty": "No messages yet — they will appear here once you subscribe"
"msg.expiry": "Message Expiry"
"msg.filter_placeholder": "Filter by topic or content…"
"msg.latest_only": "Showing latest {n} only"
"msg.log_title": "Connection Logs"
"msg.no_logs": "No logs yet"
"msg.no_match": "No matching messages"
"msg.pause_tooltip": "Pause message stream (messages keep arriving in background)"
"msg.payload": "Payload"
"msg.payload_copied": "Payload copied"
"msg.resume_tooltip": "Resume live scrolling"
"msg.seconds": "{n}s"
"msg.topic": "Topic"
"msg.topic_copied": "Topic copied"
"msg.truncated": "Truncated {n}KB"
"preset.default_name": "New preset"
"preset.default_name_n": "New preset {n}"
"preset.empty": "No presets yet — click \"New\" above to create one"
"preset.manage_title": "Manage Publish Presets"
"preset.name_exists": "Preset name \"{name}\" already exists"
"preset.payload_field": "Payload (stored raw; variables rendered on send)"
"preset.payload_format": "Payload format"
"preset.pick_delete_first": "Select a preset to delete first"
"preset.pick_first": "Select or create a preset first"
"preset.saved": "Preset \"{name}\" saved"
"preset.section": "Publish Presets"
"preset.user_props": "User Properties"
"pub.collapse": "Collapse publish panel"
"pub.collapsed_hint": "Publish panel collapsed"
"pub.content_type_ph": "Content-Type (optional)"
"pub.correlation_ph": "Correlation Data (optional)"
"pub.delete_confirm": "Delete preset \"{name}\"? This cannot be undone."
"pub.delete_item": "Delete \"{name}\""
"pub.delete_title": "Delete Preset"
"pub.expand": "Expand publish panel"
"pub.expiry_field": "Expiry (s)"
"pub.expiry_invalid": "Message expiry must be a non-negative integer (seconds)"
"pub.json_invalid": "Invalid JSON: {e}"
"pub.manage_presets": "Manage presets…"
"pub.mqtt5_props": "MQTT 5 Properties"
"pub.offline_not_sent": "Offline: message not sent"
"pub.payload_placeholder": "Message payload; supports {{variables}} and {{$ts}} {{$uuid}}"
"pub.payload_preset_ph": "Message payload; supports {{variables}}"
"pub.preset_menu": "Message Presets"
"pub.preset_name_hint": "Preset name, e.g. temperature-report"
"pub.preset_name_required": "Preset name is required"
"pub.preset_overwritten": "Preset \"{name}\" overwritten"
"pub.preset_saved": "Preset saved"
"pub.response_topic_ph": "Response Topic (optional)"
"pub.save_preset": "Save current as preset…"
"pub.save_title": "Save Message Preset"
"pub.seconds_hint": "seconds, e.g. 60"
"pub.send_disabled": "Offline — cannot send"
"pub.sent_hidden": "Sent (hidden by current filter — not shown in the stream)"
"pub.topic_placeholder": "Publish topic"
"pub.topic_preset_ph": "Publish topic; supports {{variables}}"
"pub.topic_required": "Publish topic cannot be empty"
"pub.vars": "Variable injection"
"pub.vars_count": "Variable injection ({n} placeholders)"
"resmon.auto_refresh": "Auto refresh"
"resmon.budget": "Budget {p}% used ({used} / {total})"
"resmon.committed": "Committed memory"
"resmon.committed_hint": "Physical pages committed by the process"
"resmon.cpu": "CPU usage"
"resmon.cpu_hint": "Normalized by core count"
"resmon.n_msgs": "{n} msgs"
"resmon.no_conn": "No connections"
"resmon.peak": "Peak {v}"
"resmon.refresh_now": "Refresh now"
"resmon.section": "Messages & Connections"
"resmon.stats": "{n} connections ({m} connected) · {t} tabs · {msgs} messages in memory (cap {cap}/conn) · {logs} log lines"
"resmon.threads_handles": "Threads · handles"
"resmon.threads_hint": "tokio engine + GPUI renderer"
"resmon.uptime": "Up {t}"
"resmon.version_live": "Version v{v} · refreshes every 1.5s"
"resmon.version_paused": "Version v{v} · auto-refresh paused"
"resmon.working_set": "Working set"
"settings.about": "About"
"settings.auto_update": "Check for updates on start"
"settings.byte_budget": "Plus a per-connection byte budget of {n} MB: under heavy traffic, oldest messages are evicted by size first"
"settings.data_dir": "Data directory"
"settings.language": "Language"
"settings.license": "Apache-2.0 license"
"settings.log_dir": "Log directory"
"settings.max_messages": "Messages kept in memory per connection (100-100000)"
"settings.mkdir_failed": "Failed to create log folder: {e}"
"settings.open_dir": "Open folder"
"settings.open_dir_failed": "Failed to open folder: {e}"
"settings.open_log_dir": "Open log folder"
"settings.show_millis": "Show milliseconds in timestamps"
"settings.tagline": "A cross-platform MQTT debug client built with GPUI, aiming at MQTTX"
"settings.theme": "Theme"
"settings.version_line": "Version {v} (update source: {src})"
"sidebar.collapse": "Collapse sidebar (Ctrl+B)"
"sidebar.connections": "Connections"
"sidebar.delete": "Delete Connection"
"sidebar.delete_confirm": "Delete \"{name}\"? This also deletes {sub_count} subscriptions and disconnects. This cannot be undone."
"sidebar.disconnect": "Disconnect"
"sidebar.dup_suffix": "{name} (copy)"
"sidebar.duplicate": "Duplicate"
"sidebar.empty": "No connections yet. Click + above to create one"
"sidebar.expand": "Expand sidebar (Ctrl+B)"
"sidebar.no_match": "No matching connections"
"sidebar.search": "Search connections…"
"sidebar.ungrouped": "Ungrouped"
"ssl.ca": "CA certificate (PEM)"
"ssl.ca_ph": "Path to CA certificate (PEM, optional)"
"ssl.cert": "Client certificate (PEM)"
"ssl.cert_ph": "Path to client certificate (PEM, optional)"
"ssl.key": "Client key (PEM)"
"ssl.key_ph": "Path to client private key (PEM, optional)"
"ssl.n_configured": "{n} configured"
"ssl.pick_file": "Select certificate / key file"
"ssl.section": "SSL/TLS"
"ssl.skip_verify": "Skip CA verification (trust any server cert)"
"status.connected": "Connected"
"status.connecting": "Connecting"
"status.disconnected": "Disconnected"
"status.error": "Error"
"sub.alias": "Alias (optional)"
"sub.cancel_edit": "Cancel editing"
"sub.collapse": "Collapse subscriptions panel"
"sub.color": "Subscription color"
"sub.color_clear": "Clear color"
"sub.color_random": "Random color"
"sub.disable": "Disable subscription"
"sub.edit": "Edit subscription"
"sub.editing": "Editing: {topic}"
"sub.empty_hint": "Subscribe to a topic and messages will show up here"
"sub.enable": "Enable subscription"
"sub.expand": "Expand subscriptions panel"
"sub.failed": "Subscribe failed: {e}"
"sub.identifier": "Subscription Identifier"
"sub.identifier_field": "Subscription Identifier"
"sub.identifier_invalid": "Subscription identifier must be a positive integer"
"sub.mqtt5_options": "MQTT 5 Subscription Options"
"sub.no_local": "No Local"
"sub.rap": "Retain As Published"
"sub.retain_handling": "Retain Handling"
"sub.rh0": "0 Send at every subscribe"
"sub.rh1": "1 Send only for new subscription"
"sub.rh2": "2 Do not send"
"sub.saved_offline": "Offline: subscription saved"
"sub.saved_offline_resub": "Offline: subscription saved, restored on connect"
"sub.topic_placeholder": "Topic filter, supports # +; separate multiple with commas/spaces"
"sub.topic_required": "Topic filter cannot be empty"
"sub.unsubscribe": "Unsubscribe"
"tab.welcome_hint": "Pick a connection on the left, or create a new one to start debugging"
"tab.welcome_title": "Get started with MQTTX"
"theme.dark": "Dark"
"theme.light": "Light"
"theme.system": "Follow system"
"titlebar.aliyun": "Alibaba Cloud Devices"
"titlebar.export": "Export Connections"
"titlebar.import": "Import Connections"
"titlebar.new_connection": "New Connection"
"titlebar.pin": "Pin window on top"
"titlebar.pin_failed": "Failed to set always-on-top"
"titlebar.resmon": "Resource Monitor"
"titlebar.settings": "Settings"
"titlebar.subtitle": "MQTT debug client"
"titlebar.switch_dark": "Switch to dark theme"
"titlebar.switch_light": "Switch to light theme"
"titlebar.unpin": "Unpin window"
"titlebar.variables": "Global Variables"
"update.apply": "Update to v{v} now"
"update.check": "Check for updates"
"update.check_hint": "Check GitHub Releases for a new version"
"update.checking": "Checking…"
"update.checking_long": "Checking for updates…"
"update.discard": "Discard this update"
"update.discarded": "Staged update discarded"
"update.downloading": "Downloading {pct}% ({done} / {total})"
"update.downloading_size": "Downloading {done}"
"update.failed": "Update failed: {e}"
"update.found": "New version v{v} found — downloads, replaces itself and restarts"
"update.install_failed": "Install failed: {e}"
"update.install_later": "Install on next start"
"update.install_now": "Install now"
"update.not_now": "Not now"
"update.ready": "Version v{v} downloaded and verified, ready to install"
"update.ready_body": "Version v{v} has been downloaded (sha256 verified)."
"update.ready_title": "Update Ready"
"update.recheck": "Check again"
"update.staged": "Staged — it will install on next start"
"update.up_to_date": "You are up to date"
"var.builtin_inline": "Built-in: {{$ts}} (s), {{$ts_ms}} (ms), {{$uuid}} · injected on publish"
"var.dialog_builtin": "Built-in: {{$ts}} (s), {{$ts_ms}} (ms), {{$uuid}}"
"var.dialog_hint": "Reference {{variables}} in publish topics and payloads."
"var.no_reference": "No {{variable}} reference in topic/payload"
"var.preview": "Preview: {tp} | {pl}"
"var.reextract": "Re-extract placeholders"
"var.section": "Variables ({n})"
"var.value": "Value"
"will.enabled_hint": "Enabled"
"will.topic_required": "Will topic cannot be empty"
"will.topic_wildcard": "Will topic cannot contain wildcards + or #"