From d1e2ca97adb82f85401e955ee221fa2be083608c Mon Sep 17 00:00:00 2001 From: slkass <78346291+slkass@users.noreply.github.com> Date: Thu, 5 Nov 2026 00:07:54 +0800 Subject: [PATCH] Add Simplified Chinese localization --- README.md | 4 +- crates/open-controller-core/src/i18n.rs | 28 +- crates/open-controller-core/src/i18n/zh.rs | 457 +++++++++++++++++++++ crates/open-controller-ui/src/main.rs | 5 +- 4 files changed, 485 insertions(+), 9 deletions(-) create mode 100644 crates/open-controller-core/src/i18n/zh.rs diff --git a/README.md b/README.md index 4b7fb26..e819e93 100644 --- a/README.md +++ b/README.md @@ -159,8 +159,8 @@ the name Windows has for the device ("8BitDo Ultimate 2 Wireless Controller for "XInput Controller"), and generic names are replaced from a table of 922 known models. A controller that copies another's ids, as the Onikuma C1 copies the Switch Pro Controller's, can be told which model it is under Model on its Information page, and takes that name and drawing. -The interface follows Windows' light or dark mode, and is in English or Brazilian Portuguese, picked in -Settings (English until you pick). +The interface follows Windows' light or dark mode, and is in English, Brazilian Portuguese or +Simplified Chinese, picked in Settings (English until you pick). ![A controller's page: the 8BitDo drawn with its live input, its profile, and its four extra buttons, one assigned to Xbox A, one to Ctrl+Shift+M and one to a macro](docs/controller.png) diff --git a/crates/open-controller-core/src/i18n.rs b/crates/open-controller-core/src/i18n.rs index a4217bc..a9b00b3 100644 --- a/crates/open-controller-core/src/i18n.rs +++ b/crates/open-controller-core/src/i18n.rs @@ -1,9 +1,12 @@ -//! Interface text in English and Brazilian Portuguese. English until the user picks another -//! language in the settings, which keep the choice. Strings with `{}` take one value, filled in -//! by [`fill`]. +//! Interface text in English, Brazilian Portuguese and Simplified Chinese. English until the +//! user picks another language in the settings, which keep the choice. Strings with `{}` take +//! one value, filled in by [`fill`]. use serde::{Deserialize, Serialize}; +mod zh; +pub use zh::ZH; + /// A language the interface is written in. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] @@ -11,16 +14,19 @@ pub enum Lang { #[default] En, Pt, + #[serde(rename = "zh-cn", alias = "zh", alias = "zh-CN")] + ZhCn, } impl Lang { - pub const ALL: [Lang; 2] = [Lang::En, Lang::Pt]; + pub const ALL: [Lang; 3] = [Lang::En, Lang::Pt, Lang::ZhCn]; /// Its name in itself, as language pickers show it. pub fn name(self) -> &'static str { match self { Lang::En => "English", Lang::Pt => "Português", + Lang::ZhCn => "简体中文", } } } @@ -1382,14 +1388,16 @@ pub fn fill(template: &str, value: impl std::fmt::Display) -> String { template.replacen("{}", &value.to_string(), 1) } -/// The text in `lang`. `OPEN_CONTROLLER_LANG=en` or `pt` overrides it. +/// The text in `lang`. `OPEN_CONTROLLER_LANG=en`, `pt` or `zh-cn` overrides it. pub fn text(lang: Lang) -> &'static Text { match std::env::var("OPEN_CONTROLLER_LANG").as_deref() { Ok("en") => &EN, Ok("pt") => &PT, + Ok("zh" | "zh-cn" | "zh-CN") => &ZH, _ => match lang { Lang::En => &EN, Lang::Pt => &PT, + Lang::ZhCn => &ZH, }, } } @@ -1402,6 +1410,8 @@ mod tests { fn fill_replaces_the_placeholder() { assert_eq!(fill(EN.player, 2), "Player 2"); assert_eq!(fill(PT.wait_ms, 50), "Esperar 50 ms"); + assert_eq!(fill(ZH.player, 2), "玩家 2"); + assert_eq!(fill(ZH.wait_ms, 50), "等待 50 毫秒"); } #[test] @@ -1410,4 +1420,12 @@ mod tests { assert_eq!(serde_json::from_str::(r#""en""#).unwrap(), Lang::En); assert_eq!(Lang::default(), Lang::En); } + + #[test] + fn simplified_chinese_language_names_round_trip() { + assert_eq!(serde_json::to_string(&Lang::ZhCn).unwrap(), r#""zh-cn""#); + for name in ["zh", "zh-cn", "zh-CN"] { + assert_eq!(serde_json::from_str::(&format!("\"{name}\"")).unwrap(), Lang::ZhCn); + } + } } diff --git a/crates/open-controller-core/src/i18n/zh.rs b/crates/open-controller-core/src/i18n/zh.rs new file mode 100644 index 0000000..89a0d18 --- /dev/null +++ b/crates/open-controller-core/src/i18n/zh.rs @@ -0,0 +1,457 @@ +//! Simplified Chinese interface text. Keep placeholders in the same order as English. + +use super::Text; + +pub const ZH: Text = Text { + controllers: "手柄", + controllers_one: "1 个手柄", + controllers_many: "个手柄", + empty_title: "尚未连接手柄", + empty_body: "通过数据线连接或蓝牙配对手柄。连接后会显示在这里,并在游戏中模拟为 Xbox 手柄。", + bluetooth_settings: "蓝牙设置", + player: "玩家 {}", + reconnecting: "正在重新连接,{} 秒", + fifth: "无可用 XInput 槽位", + native: "Xbox 手柄", + unmapped: "未知按键布局", + unavailable: "游戏暂时无法识别", + kept_native: "原生模式", + usb: "USB", + bluetooth: "蓝牙", + dongle: "接收器", + wireless: "无线", + charging: "正在充电", + charged: "已充满", + options: "选项", + hide_originals: "隐藏原始手柄", + hide_originals_hint: "让游戏只识别模拟的 Xbox 手柄,避免重复输入。需要 HidHide。", + start_with_windows: "开机启动", + start_with_windows_hint: "启动后驻留在系统托盘。", + on: "开", + off: "关", + about: "关于", + quit_hint: "关闭窗口后手柄仍会工作;退出程序才会停止映射。", + vigem_missing: "尚未安装虚拟手柄驱动 ViGEmBus,游戏将无法识别模拟手柄。", + hidhide_missing: "尚未安装 HidHide,直接支持 PlayStation 或 Switch 手柄的游戏可能收到重复输入。", + viiper_fallback: "VIIPER 启动失败,已改用 ViGEmBus 创建手柄。请查看设置。", + install: "安装", + tray_off: "OpenController 未运行,请启动它以使用手柄映射。", + window_failed: "无法打开窗口,手柄映射仍在运行。在终端中运行 open-controller-ui 可查看原因。", + open: "打开", + quit: "退出", + back: "手柄", + identify: "震动识别", + turn_off: "关闭手柄", + split_joycons: "拆分 Joy-Con", + join_joycons: "合并 Joy-Con", + in_games: "游戏中的设备", + as_xbox: "Xbox 手柄 {}", + as_xbox_fifth: "第 5 个或更后的 Xbox 手柄:XInput 游戏最多识别 4 个", + as_itself: "游戏直接读取,无需模拟", + waiting_slot: "重连期间保留槽位 {} 秒", + original_hidden: "已向游戏隐藏原始手柄", + original_visible: "游戏也能识别原始手柄", + as_native: "原始手柄,不创建 Xbox 手柄", + keep_native: "保持原生:游戏直接读取真实手柄。", + native_close_game: "切换前请先关闭游戏。", + native_profiles_off: "原生模式下不应用配置方案、陀螺仪瞄准和按键映射。", + native_all_alike: "此设置适用于所有相同型号的手柄。", + native_not_hidden: "关闭“隐藏原始手柄”时,此选项仅移除模拟的 Xbox 手柄。", + features: "支持的功能", + touchpad: "触摸板", + motion: "运动传感器", + rumble: "震动", + trigger_rumble: "扳机震动", + light_bar: "灯条", + player_lights: "玩家指示灯", + extra_buttons: "额外按键", + extras_hint: "游戏无法直接读取这些按键。在手柄上按下即可选中。", + no_extras: "此手柄没有超出 Xbox 标准布局的额外按键。", + no_extras_native: "游戏直接读取此手柄,因此保留原始按键功能。", + hint_8bitdo: "当前 Xbox 模式无法读取额外按键。请关闭手柄,按住 B 键开机,再放回充电底座以保存模式。", + hint_8bitdo_switch: "当前 Xbox 模式无法读取额外按键。若手柄有 D 档模式开关(Ultimate 2.4G、Pro 2),请拨到 D(D-input)。Ultimate Bluetooth 没有 D-input 模式,背键只能通过八位堂应用映射为其他按键。", + hint_elite: "Windows 不提供拨片输入,请在 Xbox 配件应用中将拨片分配为其他按键。", + restore_defaults: "恢复默认", + reset_confirm: "清除所有按键分配", + not_assigned: "未分配", + all_buttons: "全部按键", + all_buttons_hint: "任意按键均可映射为其他手柄按键、键盘按键或宏,每个配置方案单独保存。", + normal_buttons: [ + "下方面键", + "右方面键", + "左方面键", + "上方面键", + "左肩键", + "右肩键", + "中间左键", + "中间右键", + "主页键", + "左摇杆按下", + "右摇杆按下", + "方向键上", + "方向键下", + "方向键左", + "方向键右", + ], + letters: "按手柄标注的字母映射", + letters_desc: "底部标注 B 的按键在游戏中对应 B,而非按位置对应 A。", + remapped: "已重新映射", + remapped_hint: "当前配置方案修改了部分按键的功能。", + macro_steps: "宏,{} 步", + back_left: "左背键", + back_right: "右背键", + back_left2: "左背键 2", + back_right2: "右背键 2", + touchpad_click: "触摸板按下", + capture: "截图键", + mic: "麦克风键", + share: "分享键", + extra_n: "额外按键 {}", + tab_xbox: "Xbox 按键", + tab_key: "键盘按键", + tab_macro: "宏", + tab_nothing: "无操作", + tab_default: "默认", + xbox_desc: "按住此键时持续按下指定的 Xbox 按键。", + xbox_several: "同时按下多个按键", + xbox_several_desc: "选择需要同时按下的所有按键,例如 A 和 B。", + key_desc: "按住手柄按键时持续按下指定的键盘按键。", + press_key: "按下键盘按键或组合键", + listening: "等待按键", + change: "更改", + other_keys: "选择其他特殊按键", + macro_desc: "每次按下手柄按键时执行一次。", + macro_desc_xbox: "每次按下执行一次。录制时,键盘输入来自键盘,Xbox 按键输入来自手柄。", + macro_empty: "录制键盘按键,或在按键之间添加等待。", + macro_empty_xbox: "录制键盘或手柄按键,或在按键之间添加等待。", + record: "录制", + stop: "停止", + add_wait: "添加等待", + wait_ms: "等待 {} 毫秒", + clear: "清空", + nothing_desc: "此按键不执行任何操作。", + default_desc: "保留按键原本的功能。", + done: "完成", + settings: "设置", + requirements: "驱动与依赖", + requirements_hint: "OpenController 在 Windows 上所需的驱动,以及部分手柄的额外依赖。", + connect_tile: "连接手柄", + connect_tile_hint: "数据线或蓝牙", + needs_attention: "有项目需要处理", + see_requirements: "查看驱动与依赖", + nav_buttons: "按键", + nav_light: "灯光", + nav_info: "信息", + profile: "配置方案", + default_profile: "默认", + new_profile: "新建配置方案", + profile_n: "配置方案 {}", + rename: "重命名", + delete: "删除", + profiles_hint: "每个配置方案单独保存按键和灯光设置。新方案会复制当前方案。", + light_desc: "OpenController 运行时灯条的显示方式。", + light_player: "玩家颜色", + light_player_desc: "与主机相同,使用蓝、红、绿或粉色。", + light_color: "自定义颜色", + light_battery: "显示电量", + light_battery_desc: "满电为绿色,半电为黄色,需要充电时为红色。", + light_off: "关闭", + light_off_desc: "略微节省电量。", + brightness: "亮度", + no_light: "此手柄没有可由 OpenController 调整的灯光。", + info_model: "型号", + model_alias_hint: "部分手柄使用其他型号的 USB 标识,OpenController 无法自动区分。请选择实际型号,以显示正确的名称和外观。", + info_usb_id: "USB 标识", + info_connection: "连接方式", + info_battery: "电量", + required: "必需", + recommended: "推荐", + optional: "可选", + vigem_desc: "创建供游戏识别的虚拟 Xbox 手柄。", + hidhide_desc: "向游戏隐藏原始手柄,避免同一个手柄被识别两次。", + hidhide_no_arm64: "暂不支持 ARM 处理器", + ps3_title: "PlayStation 3 手柄", + ps3_desc: "Windows 没有自带 DualShock 3 驱动。将 DsHidMini 设为 SXS 模式后可通过 USB 使用,BthPS3 可添加蓝牙支持。", + dshidmini_desc: "通过 USB 使用 DualShock 3 和 Sixaxis。", + bthps3_desc: "通过蓝牙使用 DualShock 3,需要先通过数据线配对一次。", + viiper_title: "VIIPER(实验性)", + viiper_desc: "仅在高级设置中选择 VIIPER 时需要。安装 usbip-win2 后需要重启 Windows。", + usbip_desc: "VIIPER 用于连接虚拟手柄的 USB 驱动。安装时 USB 设备会短暂重新连接。", + viiper_server_desc: "用于创建 VIIPER 手柄的服务程序,由 OpenController 启动和停止。", + advanced: "高级", + virtual_driver: "虚拟手柄驱动", + virtual_driver_hint: "默认使用推荐的 ViGEmBus。", + virtual_driver_tip: "若游戏无法识别手柄,或 OpenController 运行时电脑出现蓝屏,可尝试另一种驱动,随时可以切换回来。", + driver_vigem: "ViGEmBus(推荐)", + driver_viiper: "VIIPER(实验性)", + experimental: "实验性", + driver_switch_warning: "切换前请关闭游戏,虚拟手柄将重新创建。", + viiper_missing: "VIIPER 需要上方“驱动与依赖”中的 usbip-win2 和服务程序,安装前将使用 ViGEmBus。", + viiper_failed: "VIIPER 启动失败,已使用 ViGEmBus:{}", + installed_version: "已安装,版本 {}", + installed: "已安装", + not_installed: "未安装", + update_available: "可更新至版本 {}", + hidhide_update_available: "可更新至版本 {}。安装程序会要求重启 Windows,重启后将再次打开以完成安装。", + update: "更新", + installing: "正在安装", + restart_needed: "请重启 Windows 以完成安装。", + install_failed: "安装失败:{}", + install_cancelled: "已取消安装。", + install_note: "从驱动作者的 GitHub 页面下载并校验后运行,Windows 将请求授权。", + app_update: "OpenController {} 已发布。", + update_now: "立即更新", + update_download: "下载", + update_notes: "更新内容", + update_working: "正在下载更新…", + update_failed: "无法下载更新({})。", + check_updates: "检查更新", + check_updates_hint: "打开窗口时向 GitHub 查询新版本,不发送其他信息。", + language: "语言", + start_with_system: "登录时启动", + start_with_system_hint: "在后台运行,不打开窗口。", + hide_originals_hint_linux: "让游戏只识别模拟的 Xbox 手柄,避免重复输入。", + requirements_hint_linux: "OpenController 在 Linux 上所需的权限,只需设置一次。", + requirements_hint_mac: "OpenController 在 macOS 上所需的权限。", + device_access: "设备访问权限", + device_access_desc: "安装 udev 规则,以允许创建 Xbox 手柄并完整读取已知手柄。需要输入一次密码。", + device_access_missing: "OpenController 暂时无法创建手柄,请在设置中配置设备访问权限。", + device_access_outdated: "此版本支持更多手柄,请更新规则以包含它们。", + reconnect_controllers: "设置完成,请重新连接手柄以启用完整读取。", + no_uinput: "系统内核没有 uinput 模块,OpenController 无法创建手柄。WSL 和部分自定义内核存在此限制。", + no_password_prompt: "无法请求管理员密码。请在终端运行 install.sh,或使用 README 中的命令。", + steam_deck_password: "Steam Deck 用户尚未设置密码。请打开 Konsole,运行 passwd 设置密码后重试。", + set_up: "设置权限", + accessibility: "辅助功能", + accessibility_desc: "允许 OpenController 将额外按键转换为键盘输入和宏。", + accessibility_missing: "请在辅助功能中允许 OpenController,以便向其他应用发送键盘输入和宏。", + allowed: "已允许", + not_allowed: "尚未允许", + open_system_settings: "打开系统设置", + mac_note: "macOS 不允许应用创建虚拟游戏手柄,游戏会直接读取 PlayStation、Xbox 和 Switch Pro 手柄。OpenController 提供额外按键的键盘映射和宏、灯条和电量功能。", + project_page: "项目主页", + hint_8bitdo_2c: "使用接收器时无法读取 L4 和 R4,请通过蓝牙连接以使用这些按键。", + hint_8bitdo_xbox: "此型号的额外按键只能通过八位堂应用映射为其他按键,程序无法单独读取。", + hint_steam: "Steam 运行时会占用此手柄。请关闭 Steam 或停用此手柄的 Steam Input,以便 OpenController 读取。", + hint_flydigi: "要读取 M1 至 M4,请在飞智空间站中开启“允许第三方应用接管映射”。", + hint_switch2: "暂不支持 Switch 2 手柄:当前 SDL 版本只能通过 libusb 读取。", + linux_direct_read: "Linux 上的 Steam Input 和许多 SDL 游戏会同时识别原始手柄和模拟的 Xbox 手柄,可能出现重复输入。遇到此情况,请在 Steam 手柄设置中关闭 PlayStation 和任天堂手柄支持。", + trackpad_left: "左触摸板按下", + trackpad_right: "右触摸板按下", + stick_touch_left: "左摇杆触摸", + stick_touch_right: "右摇杆触摸", + trigger_click_left: "L 完全按下", + trigger_click_right: "R 完全按下", + assistant: "助手键", + end_button: "端部肩键", + end_trigger: "端部扳机", + nav_motion: "体感", + nav_sticks: "摇杆", + gyro_desc: "转动手柄进行瞄准。陀螺仪输入叠加到右摇杆,摇杆仍可正常使用,多位玩家可分别使用自己的手柄瞄准。", + gyro_off: "关闭", + gyro_always: "始终启用", + gyro_aiming: "瞄准时(LT)", + gyro_holding: "按住指定按键时", + gyro_sensitivity: "灵敏度", + gyro_invert: "反转上下方向", + gyro_button: "触发按键", + gyro_button_note: "游戏仍会收到此按键的输入。", + gyro_press: "触发方式", + gyro_press_hold: "按住启用", + gyro_press_toggle: "按一下切换开关", + gyro_aim_sensitivity: "瞄准时灵敏度(LT)", + gyro_same: "保持相同", + gyro_vertical: "垂直速度", + gyro_pause: "按住时暂停", + gyro_pause_desc: "按住此键可调整手柄姿势,而不移动准星。", + gyro_none: "无", + gyro_advanced: "高级", + gyro_acceleration: "加速", + gyro_acceleration_desc: "快速转动时移动更远,慢速转动时保持精确。", + gyro_light: "轻度", + gyro_strong: "强", + gyro_custom: "自定义", + gyro_fast: "快速转动", + gyro_from: "起始速度", + gyro_to: "完全加速速度", + gyro_tightening: "稳定慢速移动", + gyro_tightening_desc: "缩小低于此速度的动作,减少手抖引起的准星移动。", + gyro_anti_deadzone: "陀螺仪反死区", + gyro_anti_deadzone_desc: "慢速转动时输出的最小推杆幅度,让游戏能够响应。通常为 12%。", + sticks_desc: "调整传递给游戏的摇杆输入。游戏通常自带死区和曲线,建议仅在摇杆漂移、无法到达边缘或微调瞄准过快时修改。", + deadzone: "死区", + anti_deadzone: "反死区", + dpad_stick: "摇杆模拟方向键", + dpad_stick_desc: "用于通过方向键操作的游戏,将摇杆转换为八方向按键输入。", + stick_left: "左摇杆", + stick_right: "右摇杆", + deadzone_desc: "忽略中心附近的小幅移动,减少摇杆漂移。", + anti_deadzone_desc: "越过死区后立即输出足够幅度,避免游戏自身的死区吞掉小幅移动。", + full_tilt: "满幅阈值", + full_tilt_desc: "达到此幅度即视为推到底。摇杆磨损、无法到达边缘时可降低。", + curve: "响应曲线", + curve_desc: "精确曲线在中心附近移动更慢,便于细瞄,边缘仍为全速;快速曲线相反。自定义数值为幂指数:1 为线性,2 使一半行程输出四分之一。", + curve_linear: "线性", + curve_precise: "精确", + curve_very_precise: "更精确", + curve_quick: "快速", + sticks_same: "左右摇杆使用相同设置", + sticks_same_desc: "关闭后可分别设置,例如仅为右摇杆选择精确瞄准曲线。", + sticks_editing: "正在调整", + custom_value: "自定义", + decimal: ".", + custom_value_is: "自定义:{}", + custom_range: "范围 {} 至 {},按 Enter 完成。", + sticks_preview_desc: "移动摇杆可预览游戏收到的输入:圆环表示实际位置,圆点表示输出位置。", + centre_corrected: "已按测量结果校正中心 {}%。", + centre_reset: "撤销", + measure: "校准摇杆", + measure_both: "校准左右摇杆", + measure_desc: "测量静止位置和最大行程,自动设置中心、死区和满幅阈值。约需十秒。", + measure_start: "开始校准", + measure_cancel: "取消", + measure_again: "重新校准", + measure_rest_one: "请松开摇杆并等待…", + measure_rest_both: "请松开两个摇杆并等待…", + measure_edge_left: "请将左摇杆推到底,沿边缘缓慢转圈,直到圆环填满。", + measure_edge_right: "请将右摇杆推到底,沿边缘缓慢转圈,直到圆环填满。", + measure_result: "{}:中心偏移 {}%,静止抖动 {}%,最大行程 {}%。", + measure_applied: "校准完成,已根据测量结果更新中心、死区和满幅阈值。", + measure_moved: "静止测量时检测到移动,请松开摇杆后重试。", + measure_incomplete: "未完成整圈测量,请将摇杆抵住边缘缓慢转一整圈后重试。", + measure_no_input: "未收到摇杆输入,请确认手柄已连接后重试。", + pressure_title: "压感按键", + pressure_desc: "与 PlayStation 2、3 相同,可用按键力度控制扳机,例如赛车游戏中按叉键加速;方向键力度也可控制摇杆。实验性功能。", + pressure_lt: "左扳机(LT)", + pressure_rt: "右扳机(RT)", + pressure_keep: "同时保留原始按键输入", + pressure_keep_desc: "关闭后,按键仅控制扳机或摇杆。", + pressure_dpad: "方向键模拟摇杆", + pressure_dpad_desc: "方向键按得越重,摇杆幅度越大。已模拟为方向键的摇杆不会再作为模拟摇杆使用。", + cross: "叉键", + circle: "圆圈键", + square: "方块键", + triangle: "三角键", + ds3_motion_note: "实验性功能。DualShock 3 的陀螺仪仅检测水平转动,上下倾斜由加速度计计算,也会受到晃动影响。若读数异常,可在信息页面报告问题并发送测量数据。", + gyro_tilt: "通过加速度计计算上下倾斜", + gyro_tilt_desc: "关闭后,陀螺仪仅控制水平方向瞄准。", + motion_to_games: "向游戏传递体感数据", + motion_to_games_desc: "模拟为带陀螺仪和加速度计的 DualShock 4,供 Steam Input 和支持体感的游戏读取。仅支持 Xbox 手柄的游戏将无法识别。实验性功能。", + games_see: "输出设备类型", + output_xbox: "Xbox 360 手柄", + output_ds4: "DualShock 4", + output_desc: "DualShock 4 可向游戏和 Steam Input 传递体感数据,但仅支持 Xbox 的游戏无法识别。实验性功能,请先关闭游戏再更改。", + as_ds4: "DualShock 4(XInput 游戏无法识别)", + status_ds4: "模拟为 DualShock 4", + low_battery_flash: "低电量时闪烁", + low_battery_flash_desc: "电量低于 15% 时,灯光每秒闪烁一次。", + programs_title: "自动切换的应用", + programs_hint: "下列任一程序位于前台时启用此配置方案,离开前台后恢复原先选中的方案。", + add_program: "添加已打开的程序", + no_open_programs: "没有其他已打开窗口的程序。", + in_use_auto: "当前使用:{},由前台程序触发", + swap_hint: "将一个手柄拖到另一个手柄上,可交换玩家编号。", + swap_drop: "交换玩家编号", + touch_left: "触摸板左半区按下", + touch_right: "触摸板右半区按下", + touch_two: "触摸板双指触摸", + native_keys_only: "游戏直接读取此手柄,因此可将按键映射为键盘输入和宏,无法映射为 Xbox 按键。", + handheld_untested: "根据此掌机公开的键盘或 HID 输入资料读取,尚未在实机上测试。", + handheld_button: "掌机按键", + gyro_mode: "陀螺仪瞄准", + rating_verified: "已验证", + rating_compatible: "兼容", + rating_caveats: "可用,需注意", + rating_unsupported: "暂不支持", + rating_unknown: "尚未收录", + rating_verified_hint: "已使用此型号实测 OpenController,全部功能均可用。", + rating_compatible_hint: "已知型号,预计完整兼容,但尚未在此项目中实测。", + rating_caveats_hint: "可正常使用,请查看按键页面的说明以启用全部功能。", + rating_unsupported_hint: "OpenController 已识别此型号,但暂时无法读取。", + rating_unknown_hint: "多数同类手柄仍可使用,发送设备信息有助于添加支持。", + info_rating: "兼容性", + report_problem: "报告问题", + unknown_title: "此手柄尚未收录", + unknown_body: "它可能仍可正常使用。发送设备信息可帮助添加型号识别。", + unknown_send: "发送设备信息", + flight_stick_title: "这是飞行摇杆", + throttle_title: "这是油门控制器", + wheel_title: "这是赛车方向盘", + not_gamepad_body: "专门支持此设备的游戏会直接读取,因此保留原始状态。若要用于普通手柄游戏,请发送设备信息,以便添加 Xbox 布局。", + learn_offer: "OpenController 尚不清楚此设备的按键布局。可逐一映射按键,将其用作 Xbox 手柄;发送设备信息可帮助为所有用户添加支持。", + learn_start: "映射按键布局", + learn_title: "映射按键布局", + learn_desc: "按提示操作各个按键和摇杆,跳过手柄没有的部件。", + learn_count: "第 {} 步,共 {} 步", + learn_press: "请按下{}", + learn_push: "请将{}推到底", + learn_parts: [ + "下方面键(Xbox 的 A、PlayStation 的叉键)", + "右方面键(Xbox 的 B、PlayStation 的圆圈键)", + "左方面键(Xbox 的 X、PlayStation 的方块键)", + "上方面键(Xbox 的 Y、PlayStation 的三角键)", + "方向键上", + "方向键右", + "方向键下", + "方向键左", + "左肩键(LB、L1)", + "右肩键(RB、R1)", + "左扳机(LT、L2)", + "右扳机(RT、R2)", + "左摇杆向右", + "左摇杆向下", + "右摇杆向右", + "右摇杆向下", + "左摇杆(L3)", + "右摇杆(R3)", + "返回、Select 或 Share 键", + "Start 或 Options 键", + "中间的主页键(Xbox、PS 或 Home)", + ], + learn_got: "已读取({}),请松开。", + learn_skip: "没有此部件", + learn_back: "上一步", + learn_cancel: "取消", + learn_done: "已完成全部部件的映射,保存后即可使用此布局。", + learn_nothing: "尚未映射任何部件,请重新开始并按提示操作。", + learn_save: "保存", + learn_again: "重新开始", + learn_info: "按键布局", + learn_own: "自定义映射", + learn_redo: "重新映射", + native_left_as_is: "飞行摇杆、油门控制器和方向盘默认保持原生模式,以供支持它们的游戏使用。", + on_base: "已放到底座上", + report_title: "报告此手柄的问题", + report_title_unknown: "发送此手柄的设备信息", + report_intro: "将向 OpenController 维护者发送手柄技术信息,包括名称、USB 标识、系统和 SDL 的识别结果,以及最近连接的设备,帮助维护者在没有实物的情况下添加或修复支持。不会发送个人信息。", + report_model: "手柄型号", + report_model_placeholder: "品牌和型号,例如 Redragon Darkflame G820", + report_message: "遇到了什么问题?", + report_message_placeholder: "例如:背键没有反应,或左右摇杆输入颠倒", + report_email: "回复邮箱", + report_optional: "可选", + report_press: "保持此页面打开,按下有问题的按键,报告会显示收到的输入。", + report_press_gyro: "保持此页面打开,按下有问题的按键并轻轻转动手柄,报告会显示收到的输入。", + report_pressed: "已收到:{}", + report_nothing_pressed: "暂无输入", + report_show: "查看将要发送的内容", + report_hide: "收起设备信息", + report_send: "发送", + report_sending: "正在发送…", + report_cancel: "取消", + report_close: "关闭", + report_copy: "复制设备信息", + report_copied: "已复制", + report_reading: "正在读取手柄…", + report_gone: "手柄已断开,请重新连接后发送设备信息。", + report_sent_title: "已发送,谢谢!", + report_sent_body: "维护者已收到设备信息,若填写了邮箱,可能会收到回复。", + report_failed: "发送失败:{}", + report_rate: "此网络发送的报告过多,请一小时后重试,或复制设备信息并通过邮件发送。", + report_bad_email: "邮箱格式似乎不正确。", + link_starting: "正在启动 OpenController…", + link_lost: "与 OpenController 的连接已断开,正在重新连接…", + other_version: "当前运行的 OpenController {} 与此窗口版本不同,请重启以保持一致。", + restart: "重启程序", + update_not_closed: "OpenController 未能及时退出,更新尚未开始,请重试。", +}; diff --git a/crates/open-controller-ui/src/main.rs b/crates/open-controller-ui/src/main.rs index 267a8a1..55a922b 100644 --- a/crates/open-controller-ui/src/main.rs +++ b/crates/open-controller-ui/src/main.rs @@ -437,12 +437,13 @@ fn has_display() -> bool { ["WAYLAND_DISPLAY", "DISPLAY"].iter().any(|v| std::env::var_os(v).is_some_and(|d| !d.is_empty())) } -/// `OPEN_CONTROLLER_LANG=en` or `pt` shows the window in that language whatever was picked, for -/// screenshots. +/// `OPEN_CONTROLLER_LANG=en`, `pt` or `zh-cn` shows the window in that language whatever was +/// picked, for screenshots. fn forced_lang() -> Option { match std::env::var("OPEN_CONTROLLER_LANG").ok()?.as_str() { "en" => Some(Lang::En), "pt" => Some(Lang::Pt), + "zh" | "zh-cn" | "zh-CN" => Some(Lang::ZhCn), _ => None, } }