From 5b25b3661f28deda2d836f970387465ebfd6896a Mon Sep 17 00:00:00 2001 From: mofeng-git Date: Mon, 12 Aug 2024 22:58:01 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9B=E4=B8=80=E6=AD=A5=E7=9A=84=20kvmd=20?= =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96=EF=BC=88=E6=B1=89=E5=8C=96=EF=BC=89?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kvmd/aiohelpers.py | 6 +- kvmd/aioproc.py | 11 +- kvmd/apps/kvmd/streamer.py | 41 +++-- kvmd/apps/kvmd/ugpio.py | 30 +-- kvmd/apps/otg/__init__.py | 31 ++-- kvmd/apps/otgnet/__init__.py | 22 ++- kvmd/i18n/zh/LC_MESSAGES/message.mo | Bin 8047 -> 12244 bytes kvmd/i18n/zh/LC_MESSAGES/message.po | 272 ++++++++++++++++++++++++++-- kvmd/keyboard/keysym.py | 6 +- kvmd/plugins/hid/otg/__init__.py | 4 +- message.pot | 266 +++++++++++++++++++++++++-- 11 files changed, 599 insertions(+), 90 deletions(-) diff --git a/kvmd/aiohelpers.py b/kvmd/aiohelpers.py index c3b257d1..a0b86399 100644 --- a/kvmd/aiohelpers.py +++ b/kvmd/aiohelpers.py @@ -22,6 +22,8 @@ import subprocess +from .lanuages import Lanuages + from .logging import get_logger from . import tools @@ -36,13 +38,13 @@ async def remount(name: str, base_cmd: list[str], rw: bool) -> bool: part.format(mode=mode) for part in base_cmd ] - logger.info("Remounting %s storage to %s: %s ...", name, mode.upper(), tools.cmdfmt(cmd)) + logger.info(Lanuages().gettext("Remounting %s storage to %s: %s ..."), name, mode.upper(), tools.cmdfmt(cmd)) try: proc = await aioproc.log_process(cmd, logger) if proc.returncode != 0: assert proc.returncode is not None raise subprocess.CalledProcessError(proc.returncode, cmd) except Exception as err: - logger.error("Can't remount %s storage: %s", name, tools.efmt(err)) + logger.error(Lanuages().gettext("Can't remount %s storage: %s"), name, tools.efmt(err)) return False return True diff --git a/kvmd/aioproc.py b/kvmd/aioproc.py index 376df004..39181d0c 100644 --- a/kvmd/aioproc.py +++ b/kvmd/aioproc.py @@ -26,6 +26,7 @@ import asyncio import asyncio.subprocess import logging +from .lanuages import Lanuages import setproctitle from .logging import get_logger @@ -85,7 +86,7 @@ async def log_stdout_infinite(proc: asyncio.subprocess.Process, logger: logging. else: empty += 1 if empty == 100: # asyncio bug - raise RuntimeError("Asyncio process: too many empty lines") + raise RuntimeError(Lanuages().gettext("Asyncio process: too many empty lines")) async def kill_process(proc: asyncio.subprocess.Process, wait: float, logger: logging.Logger) -> None: # pylint: disable=no-member @@ -100,14 +101,14 @@ async def kill_process(proc: asyncio.subprocess.Process, wait: float, logger: lo if proc.returncode is not None: raise await proc.wait() - logger.info("Process killed: retcode=%d", proc.returncode) + logger.info(Lanuages().gettext("Process killed: retcode=%d"), proc.returncode) except asyncio.CancelledError: pass except Exception: if proc.returncode is None: - logger.exception("Can't kill process pid=%d", proc.pid) + logger.exception(Lanuages().gettext("Can't kill process pid=%d"), proc.pid) else: - logger.info("Process killed: retcode=%d", proc.returncode) + logger.info(Lanuages().gettext("Process killed: retcode=%d"), proc.returncode) def rename_process(suffix: str, prefix: str="kvmd") -> None: @@ -116,7 +117,7 @@ def rename_process(suffix: str, prefix: str="kvmd") -> None: def settle(name: str, suffix: str, prefix: str="kvmd") -> logging.Logger: logger = get_logger(1) - logger.info("Started %s pid=%d", name, os.getpid()) + logger.info(Lanuages().gettext("Started %s pid=%d"), name, os.getpid()) os.setpgrp() rename_process(suffix, prefix) return logger diff --git a/kvmd/apps/kvmd/streamer.py b/kvmd/apps/kvmd/streamer.py index 26904d40..87601a5f 100644 --- a/kvmd/apps/kvmd/streamer.py +++ b/kvmd/apps/kvmd/streamer.py @@ -34,6 +34,8 @@ import aiohttp from PIL import Image as PilImage +from ...lanuages import Lanuages + from ...logging import get_logger from ... import tools @@ -226,6 +228,9 @@ class Streamer: # pylint: disable=too-many-instance-attributes self.__notifier = aiotools.AioNotifier() + self.gettext=Lanuages().gettext + + # ===== @aiotools.atomic_fg @@ -237,15 +242,15 @@ class Streamer: # pylint: disable=too-many-instance-attributes if not self.__stop_wip: self.__stop_task.cancel() await asyncio.gather(self.__stop_task, return_exceptions=True) - logger.info("Streamer stop cancelled") + logger.info(self.gettext("Streamer stop cancelled")) return else: await asyncio.gather(self.__stop_task, return_exceptions=True) if reset and self.__reset_delay > 0: - logger.info("Waiting %.2f seconds for reset delay ...", self.__reset_delay) + logger.info(self.gettext("Waiting %.2f seconds for reset delay ..."), self.__reset_delay) await asyncio.sleep(self.__reset_delay) - logger.info("Starting streamer ...") + logger.info(self.gettext("Starting streamer ...")) await self.__inner_start() @aiotools.atomic_fg @@ -258,12 +263,12 @@ class Streamer: # pylint: disable=too-many-instance-attributes if not self.__stop_wip: self.__stop_task.cancel() await asyncio.gather(self.__stop_task, return_exceptions=True) - logger.info("Stopping streamer immediately ...") + logger.info(self.gettext("Stopping streamer immediately ...")) await self.__inner_stop() else: await asyncio.gather(self.__stop_task, return_exceptions=True) else: - logger.info("Stopping streamer immediately ...") + logger.info(self.gettext("Stopping streamer immediately ...")) await self.__inner_stop() elif not self.__stop_task: @@ -272,13 +277,13 @@ class Streamer: # pylint: disable=too-many-instance-attributes try: await asyncio.sleep(self.__shutdown_delay) self.__stop_wip = True - logger.info("Stopping streamer after delay ...") + logger.info(self.gettext("Stopping streamer after delay ...")) await self.__inner_stop() finally: self.__stop_task = None self.__stop_wip = False - logger.info("Planning to stop streamer in %.2f seconds ...", self.__shutdown_delay) + logger.info(self.gettext("Planning to stop streamer in %.2f seconds ..."), self.__shutdown_delay) self.__stop_task = asyncio.create_task(delayed_stop()) def is_working(self) -> bool: @@ -307,7 +312,7 @@ class Streamer: # pylint: disable=too-many-instance-attributes except (aiohttp.ClientConnectionError, aiohttp.ServerConnectionError): pass except Exception: - get_logger().exception("Invalid streamer response from /state") + get_logger().exception(self.gettext("Invalid streamer response from /state")) snapshot: (dict | None) = None if self.__snapshot: @@ -325,10 +330,10 @@ class Streamer: # pylint: disable=too-many-instance-attributes async def poll_state(self) -> AsyncGenerator[dict, None]: def signal_handler(*_: Any) -> None: - get_logger(0).info("Got SIGUSR2, checking the stream state ...") + get_logger(0).info(self.gettext("Got SIGUSR2, checking the stream state ...")) self.__notifier.notify() - get_logger(0).info("Installing SIGUSR2 streamer handler ...") + get_logger(0).info(self.gettext("Installing SIGUSR2 streamer handler ...")) asyncio.get_event_loop().add_signal_handler(signal.SIGUSR2, signal_handler) waiter_task: (asyncio.Task | None) = None @@ -384,12 +389,12 @@ class Streamer: # pylint: disable=too-many-instance-attributes self.__snapshot = snapshot self.__notifier.notify() return snapshot - logger.error("Stream is offline, no signal or so") + logger.error(self.gettext("Stream is offline, no signal or so")) except (aiohttp.ClientConnectionError, aiohttp.ServerConnectionError) as err: - logger.error("Can't connect to streamer: %s", tools.efmt(err)) + logger.error(self.gettext("Can't connect to streamer: %s"), tools.efmt(err)) except Exception: - logger.exception("Invalid streamer response from /snapshot") + logger.exception(self.gettext("Invalid streamer response from /snapshot")) return None def remove_snapshot(self) -> None: @@ -446,14 +451,14 @@ class Streamer: # pylint: disable=too-many-instance-attributes await self.__start_streamer_proc() assert self.__streamer_proc is not None await aioproc.log_stdout_infinite(self.__streamer_proc, logger) - raise RuntimeError("Streamer unexpectedly died") + raise RuntimeError(self.gettext("Streamer unexpectedly died")) except asyncio.CancelledError: break except Exception: if self.__streamer_proc: - logger.exception("Unexpected streamer error: pid=%d", self.__streamer_proc.pid) + logger.exception(self.gettext("Unexpected streamer error: pid=%d"), self.__streamer_proc.pid) else: - logger.exception("Can't start streamer") + logger.exception(self.gettext("Can't start streamer")) await self.__kill_streamer_proc() await asyncio.sleep(1) @@ -474,13 +479,13 @@ class Streamer: # pylint: disable=too-many-instance-attributes try: await aioproc.log_process(cmd, logger, prefix=name) except Exception as err: - logger.exception("Can't execute command: %s", err) + logger.exception(self.gettext("Can't execute command: %s"), err) async def __start_streamer_proc(self) -> None: assert self.__streamer_proc is None cmd = self.__make_cmd(self.__cmd) self.__streamer_proc = await aioproc.run_process(cmd) - get_logger(0).info("Started streamer pid=%d: %s", self.__streamer_proc.pid, tools.cmdfmt(cmd)) + get_logger(0).info(self.gettext("Started streamer pid=%d: %s"), self.__streamer_proc.pid, tools.cmdfmt(cmd)) async def __kill_streamer_proc(self) -> None: if self.__streamer_proc: diff --git a/kvmd/apps/kvmd/ugpio.py b/kvmd/apps/kvmd/ugpio.py index 872d5f6c..2ccad33c 100644 --- a/kvmd/apps/kvmd/ugpio.py +++ b/kvmd/apps/kvmd/ugpio.py @@ -26,6 +26,8 @@ from typing import AsyncGenerator from typing import Callable from typing import Any +from ...lanuages import Lanuages + from ...logging import get_logger from ...errors import IsBusyError @@ -46,22 +48,22 @@ from ...yamlconf import Section # ===== class GpioChannelNotFoundError(GpioOperationError): def __init__(self) -> None: - super().__init__("GPIO channel is not found") + super().__init__(Lanuages().gettext("GPIO channel is not found")) class GpioSwitchNotSupported(GpioOperationError): def __init__(self) -> None: - super().__init__("This GPIO channel does not support switching") + super().__init__(Lanuages().gettext("This GPIO channel does not support switching")) class GpioPulseNotSupported(GpioOperationError): def __init__(self) -> None: - super().__init__("This GPIO channel does not support pulsing") + super().__init__(Lanuages().gettext("This GPIO channel does not support pulsing")) class GpioChannelIsBusyError(IsBusyError, GpioError): def __init__(self) -> None: - super().__init__("Performing another GPIO operation on this channel, please try again later") + super().__init__(Lanuages().gettext("Performing another GPIO operation on this channel, please try again later")) # ===== @@ -80,6 +82,8 @@ class _GpioInput: self.__driver = driver self.__driver.register_input(self.__pin, config.debounce) + self.gettext=Lanuages().gettext + def get_scheme(self) -> dict: return { "hw": { @@ -188,7 +192,7 @@ class _GpioOutput: # pylint: disable=too-many-instance-attributes await func(*args) else: await aiotools.run_region_task( - f"Can't perform {name} of {self} or operation was not completed", + self.gettext(f"Can't perform {name} of {self} or operation was not completed"), self.__region, self.__action_task_wrapper, name, func, *args, ) @@ -197,12 +201,12 @@ class _GpioOutput: # pylint: disable=too-many-instance-attributes try: return (await func(*args)) except GpioDriverOfflineError: - get_logger(0).error("Can't perform %s of %s or operation was not completed: driver offline", name, self) + get_logger(0).error(self.gettext("Can't perform %s of %s or operation was not completed: driver offline"), name, self) @aiotools.atomic_fg async def __inner_switch(self, state: bool) -> None: await self.__write(state) - get_logger(0).info("Ensured switch %s to state=%d", self, state) + get_logger(0).info(self.gettext("Ensured switch %s to state=%d"), self, state) await asyncio.sleep(self.__busy_delay) @aiotools.atomic_fg @@ -213,7 +217,7 @@ class _GpioOutput: # pylint: disable=too-many-instance-attributes finally: await self.__write(False) await asyncio.sleep(self.__busy_delay) - get_logger(0).info("Pulsed %s with delay=%.2f", self, delay) + get_logger(0).info(self.gettext("Pulsed %s with delay=%.2f"), self, delay) # ===== @@ -224,7 +228,7 @@ class _GpioOutput: # pylint: disable=too-many-instance-attributes await self.__driver.write(self.__pin, (state ^ self.__inverted)) def __str__(self) -> str: - return f"Output({self.__channel}, driver={self.__driver}, pin={self.__pin})" + return self.gettext(f"Output({self.__channel}, driver={self.__driver}, pin={self.__pin})") __repr__ = __str__ @@ -249,6 +253,8 @@ class UserGpio: self.__inputs: dict[str, _GpioInput] = {} self.__outputs: dict[str, _GpioOutput] = {} + self.gettext=Lanuages().gettext + for (channel, ch_config) in tools.sorted_kvs(config.scheme): driver = self.__drivers[ch_config.driver] if ch_config.mode == UserGpioModes.INPUT: @@ -289,12 +295,12 @@ class UserGpio: await self.__notifier.wait() def sysprep(self) -> None: - get_logger(0).info("Preparing User-GPIO drivers ...") + get_logger(0).info(self.gettext("Preparing User-GPIO drivers ...")) for (_, driver) in tools.sorted_kvs(self.__drivers): driver.prepare() async def systask(self) -> None: - get_logger(0).info("Running User-GPIO drivers ...") + get_logger(0).info(self.gettext("Running User-GPIO drivers ...")) await asyncio.gather(*[ driver.run() for (_, driver) in tools.sorted_kvs(self.__drivers) @@ -305,7 +311,7 @@ class UserGpio: try: await driver.cleanup() except Exception: - get_logger().exception("Can't cleanup driver %s", driver) + get_logger().exception(self.gettext("Can't cleanup driver %s"), driver) async def switch(self, channel: str, state: bool, wait: bool) -> None: gout = self.__outputs.get(channel) diff --git a/kvmd/apps/otg/__init__.py b/kvmd/apps/otg/__init__.py index 1da23c67..f054cd4d 100644 --- a/kvmd/apps/otg/__init__.py +++ b/kvmd/apps/otg/__init__.py @@ -27,7 +27,9 @@ import json import time import argparse -from os.path import join # pylint: disable=ungrouped-imports +from os.path import join + +from ...lanuages import Lanuages from ...logging import get_logger @@ -201,13 +203,14 @@ def _cmd_start(config: Section) -> None: # pylint: disable=too-many-statements, # https://www.isticktoit.net/?p=1383 logger = get_logger() + gettext=Lanuages().gettext _check_config(config) udc = usb.find_udc(config.otg.udc) - logger.info("Using UDC %s", udc) + logger.info(gettext("Using UDC %s"), udc) - logger.info("Creating gadget %r ...", config.otg.gadget) + logger.info(gettext("Creating gadget %r ..."), config.otg.gadget) gadget_path = usb.get_gadget_path(config.otg.gadget) _mkdir(gadget_path) @@ -248,39 +251,39 @@ def _cmd_start(config: Section) -> None: # pylint: disable=too-many-statements, cod = config.otg.devices if cod.serial.enabled: - logger.info("===== Serial =====") + logger.info(gettext("===== Serial =====")) gc.add_serial(cod.serial.start) if cod.ethernet.enabled: - logger.info("===== Ethernet =====") + logger.info(gettext("===== Ethernet =====")) gc.add_ethernet(**cod.ethernet._unpack(ignore=["enabled"])) if config.kvmd.hid.type == "otg": - logger.info("===== HID-Keyboard =====") + logger.info(gettext("===== HID-Keyboard =====")) gc.add_keyboard(cod.hid.keyboard.start, config.otg.remote_wakeup) - logger.info("===== HID-Mouse =====") + logger.info(gettext("===== HID-Mouse =====")) gc.add_mouse(cod.hid.mouse.start, config.otg.remote_wakeup, config.kvmd.hid.mouse.absolute, config.kvmd.hid.mouse.horizontal_wheel) if config.kvmd.hid.mouse_alt.device: - logger.info("===== HID-Mouse-Alt =====") + logger.info(gettext("===== HID-Mouse-Alt =====")) gc.add_mouse(cod.hid.mouse.start, config.otg.remote_wakeup, (not config.kvmd.hid.mouse.absolute), config.kvmd.hid.mouse.horizontal_wheel) if config.kvmd.msd.type == "otg": - logger.info("===== MSD =====") + logger.info(gettext("===== MSD =====")) gc.add_msd(cod.msd.start, config.otg.user, **cod.msd.default._unpack()) if cod.drives.enabled: for count in range(cod.drives.count): - logger.info("===== MSD Extra: %d =====", count + 1) + logger.info(gettext("===== MSD Extra: %d ====="), count + 1) gc.add_msd(cod.drives.start, "root", **cod.drives.default._unpack()) - logger.info("===== Preparing complete =====") + logger.info(gettext("===== Preparing complete =====")) - logger.info("Enabling the gadget ...") + logger.info(gettext("Enabling the gadget ...")) _write(join(gadget_path, "UDC"), udc) time.sleep(config.otg.init_delay) _chown(join(gadget_path, "UDC"), config.otg.user) _chown(profile_path, config.otg.user) - logger.info("Ready to work") + logger.info(gettext("Ready to work")) # ===== @@ -293,7 +296,7 @@ def _cmd_stop(config: Section) -> None: gadget_path = usb.get_gadget_path(config.otg.gadget) - logger.info("Disabling gadget %r ...", config.otg.gadget) + logger.info(Lanuages().gettext("Disabling gadget %r ..."), config.otg.gadget) _write(join(gadget_path, "UDC"), "\n") _unlink(join(gadget_path, "os_desc", usb.G_PROFILE_NAME), optional=True) diff --git a/kvmd/apps/otgnet/__init__.py b/kvmd/apps/otgnet/__init__.py index 3519d98b..0306fece 100644 --- a/kvmd/apps/otgnet/__init__.py +++ b/kvmd/apps/otgnet/__init__.py @@ -26,6 +26,8 @@ import dataclasses import itertools import argparse +from ...lanuages import Lanuages + from ...logging import get_logger from ...yamlconf import Section @@ -87,6 +89,8 @@ class _Service: # pylint: disable=too-many-instance-attributes self.__gadget: str = config.otg.gadget self.__driver: str = config.otg.devices.ethernet.driver + self.gettext=Lanuages().gettext + def start(self) -> None: asyncio.run(self.__run(True)) @@ -121,20 +125,20 @@ class _Service: # pylint: disable=too-many-instance-attributes for ctl in ctls: if not (await self.__run_ctl(ctl, True)): raise SystemExit(1) - get_logger(0).info("Ready to work") + get_logger(0).info(self.gettext("Ready to work")) else: for ctl in reversed(ctls): await self.__run_ctl(ctl, False) - get_logger(0).info("Bye-bye") + get_logger(0).info(self.gettext("Bye-bye")) async def __run_ctl(self, ctl: BaseCtl, direct: bool) -> bool: logger = get_logger() cmd = ctl.get_command(direct) - logger.info("CMD: %s", tools.cmdfmt(cmd)) + logger.info(self.gettext("CMD: %s"), tools.cmdfmt(cmd)) try: return (not (await aioproc.log_process(cmd, logger)).returncode) except Exception as err: - logger.exception("Can't execute command: %s", err) + logger.exception(self.gettext("Can't execute command: %s"), err) return False # ===== @@ -143,10 +147,10 @@ class _Service: # pylint: disable=too-many-instance-attributes iface = self.__find_iface() logger = get_logger() - logger.info("Using IPv4 network %s ...", self.__iface_net) + logger.info(self.gettext("Using IPv4 network %s ..."), self.__iface_net) net = ipaddress.IPv4Network(self.__iface_net) if net.prefixlen > 31: - raise RuntimeError("Too small network, required at least /31") + raise RuntimeError(self.gettext("Too small network, required at least /31")) if net.prefixlen == 31: iface_ip = str(net[0]) @@ -166,7 +170,7 @@ class _Service: # pylint: disable=too-many-instance-attributes dhcp_ip_end=dhcp_ip_end, dhcp_option_3=(f"3,{iface_ip}" if self.__forward_iface else "3"), ) - logger.info("Calculated %r address is %s/%d", iface, iface_ip, netcfg.net_prefix) + logger.info(self.gettext("Calculated %r address is %s/%d"), iface, iface_ip, netcfg.net_prefix) return netcfg def __find_iface(self) -> str: @@ -175,10 +179,10 @@ class _Service: # pylint: disable=too-many-instance-attributes if self.__driver == "rndis5": real_driver = "rndis" path = usb.get_gadget_path(self.__gadget, usb.G_FUNCTIONS, f"{real_driver}.usb0/ifname") - logger.info("Using OTG gadget %r ...", self.__gadget) + logger.info(self.gettext("Using OTG gadget %r ..."), self.__gadget) with open(path) as file: iface = file.read().strip() - logger.info("Using OTG Ethernet interface %r ...", iface) + logger.info(self.gettext("Using OTG Ethernet interface %r ..."), iface) assert iface return iface diff --git a/kvmd/i18n/zh/LC_MESSAGES/message.mo b/kvmd/i18n/zh/LC_MESSAGES/message.mo index ec6a1c48c7f989eee013dc964b2b1895234984de..7a1147049a854156464b685b75bf1932396a10ce 100644 GIT binary patch literal 12244 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 CG5u-) diff --git a/kvmd/i18n/zh/LC_MESSAGES/message.po b/kvmd/i18n/zh/LC_MESSAGES/message.po index 6171e244..3273b20d 100644 --- a/kvmd/i18n/zh/LC_MESSAGES/message.po +++ b/kvmd/i18n/zh/LC_MESSAGES/message.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-08-06 21:57+0800\n" -"PO-Revision-Date: 2024-08-06 21:57+0800\n" +"POT-Creation-Date: 2024-08-12 22:07+0800\n" +"PO-Revision-Date: 2024-08-12 22:07+0800\n" "Last-Translator: \n" "Language: zh\n" "Language-Team: zh \n" @@ -18,6 +18,35 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.15.0\n" +#: kvmd/aiohelpers.py:41 +#, python-format +msgid "Remounting %s storage to %s: %s ..." +msgstr "重新挂载 %s 存储到 %s: %s ......" + +#: kvmd/aiohelpers.py:48 +#, python-format +msgid "Can't remount %s storage: %s" +msgstr "无法重新挂载 %s 存储:%s" + +#: kvmd/aioproc.py:89 +msgid "Asyncio process: too many empty lines" +msgstr "Asyncio 进程:空行过多" + +#: kvmd/aioproc.py:104 kvmd/aioproc.py:111 +#, python-format +msgid "Process killed: retcode=%d" +msgstr "进程被杀死:retcode=%d" + +#: kvmd/aioproc.py:109 +#, python-format +msgid "Can't kill process pid=%d" +msgstr "无法杀死进程 pid=%d" + +#: kvmd/aioproc.py:120 +#, python-format +msgid "Started %s pid=%d" +msgstr "已启动 %s pid=%d" + #: kvmd/htclient.py:63 msgid "Can't determine filename" msgstr "无法确定文件名" @@ -91,58 +120,271 @@ msgstr "尝试使用 --help 选项来了解某项服务的功能。\n" msgid "Make sure you understand exactly what you are doing!" msgstr "请确定你自己在做什么!" -#: kvmd/apps/kvmd/__init__.py:115 +#: kvmd/apps/kvmd/__init__.py:115 kvmd/apps/otgnet/__init__.py:132 msgid "Bye-bye" msgstr "再见" -#: kvmd/apps/kvmd/auth.py:57 +#: kvmd/apps/kvmd/auth.py:58 msgid "AUTHORIZATION IS DISABLED" msgstr "身份验证服务已被禁用" -#: kvmd/apps/kvmd/auth.py:61 +#: kvmd/apps/kvmd/auth.py:62 #, python-format msgid "Authorization is disabled for API %r" msgstr "由于 API %r 身份验证服务已被禁用" -#: kvmd/apps/kvmd/auth.py:66 +#: kvmd/apps/kvmd/auth.py:67 #, python-format msgid "Using internal auth service %r" msgstr "使用内部身份验证服务 %r" -#: kvmd/apps/kvmd/auth.py:73 +#: kvmd/apps/kvmd/auth.py:74 #, python-format msgid "Using external auth service %r" msgstr "使用外部身份验证服务 %r" -#: kvmd/apps/kvmd/auth.py:101 +#: kvmd/apps/kvmd/auth.py:103 #, python-format msgid "Got access denied for user %r by TOTP" msgstr "用户 %r 被 TOTP 拒绝访问" -#: kvmd/apps/kvmd/auth.py:112 +#: kvmd/apps/kvmd/auth.py:114 #, python-format msgid "Authorized user %r via auth service %r" msgstr "用户 %r 已通过身份认证服务 %r 授权" -#: kvmd/apps/kvmd/auth.py:114 +#: kvmd/apps/kvmd/auth.py:116 #, python-format msgid "Got access denied for user %r from auth service %r" msgstr "身份验证服务 %r 拒绝了用户 %r 的访问请求" -#: kvmd/apps/kvmd/auth.py:124 +#: kvmd/apps/kvmd/auth.py:126 #, python-format msgid "Logged in user %r" msgstr "已登录用户 %r" -#: kvmd/apps/kvmd/auth.py:134 +#: kvmd/apps/kvmd/auth.py:136 msgid "Can't generate new unique token" msgstr "无法生成新的唯一令牌" -#: kvmd/apps/kvmd/auth.py:145 +#: kvmd/apps/kvmd/auth.py:147 #, python-format msgid "Logged out user %r (%d)" msgstr "已注销用户 %r (%d)" +#: kvmd/apps/kvmd/streamer.py:245 +msgid "Streamer stop cancelled" +msgstr "Streamer 停止已取消" + +#: kvmd/apps/kvmd/streamer.py:251 +#, python-format +msgid "Waiting %.2f seconds for reset delay ..." +msgstr "等待 %.2f 秒的重置延迟 ......" + +#: kvmd/apps/kvmd/streamer.py:253 +msgid "Starting streamer ..." +msgstr "正在启动 streamer......" + +#: kvmd/apps/kvmd/streamer.py:266 kvmd/apps/kvmd/streamer.py:271 +msgid "Stopping streamer immediately ..." +msgstr "正在停止 streamer......" + +#: kvmd/apps/kvmd/streamer.py:280 +msgid "Stopping streamer after delay ..." +msgstr "在延迟时间到后停止 streamer......" + +#: kvmd/apps/kvmd/streamer.py:286 +#, python-format +msgid "Planning to stop streamer in %.2f seconds ..." +msgstr "计划在 %.2f 秒后停止streamer......" + +#: kvmd/apps/kvmd/streamer.py:315 +msgid "Invalid streamer response from /state" +msgstr "来自 /state 的无效 streamer 响应" + +#: kvmd/apps/kvmd/streamer.py:333 +msgid "Got SIGUSR2, checking the stream state ..." +msgstr "收到 SIGUSR2 信号,正在检查数据流状态 ..." + +#: kvmd/apps/kvmd/streamer.py:336 +msgid "Installing SIGUSR2 streamer handler ..." +msgstr "安装 SIGUSR2 streamer 处理程序 ..." + +#: kvmd/apps/kvmd/streamer.py:392 +msgid "Stream is offline, no signal or so" +msgstr "流媒体离线,没有信号或其他原因" + +#: kvmd/apps/kvmd/streamer.py:395 +#, python-format +msgid "Can't connect to streamer: %s" +msgstr "无法连接 streamer:%s" + +#: kvmd/apps/kvmd/streamer.py:397 +msgid "Invalid streamer response from /snapshot" +msgstr "来自 /snapshot 的无效 streamer 响应" + +#: kvmd/apps/kvmd/streamer.py:454 +msgid "Streamer unexpectedly died" +msgstr "Streamer 意外停止" + +#: kvmd/apps/kvmd/streamer.py:459 +#, python-format +msgid "Unexpected streamer error: pid=%d" +msgstr "Streamer 意外错误:pid=%d" + +#: kvmd/apps/kvmd/streamer.py:461 +msgid "Can't start streamer" +msgstr "无法启动 streamer" + +#: kvmd/apps/kvmd/streamer.py:482 kvmd/apps/otgnet/__init__.py:141 +#, python-format +msgid "Can't execute command: %s" +msgstr "无法执行命令: %s" + +#: kvmd/apps/kvmd/streamer.py:488 +#, python-format +msgid "Started streamer pid=%d: %s" +msgstr "已启动 streamer pid=%d: %s" + +#: kvmd/apps/kvmd/ugpio.py:51 +msgid "GPIO channel is not found" +msgstr "GPIO 未找到" + +#: kvmd/apps/kvmd/ugpio.py:56 +msgid "This GPIO channel does not support switching" +msgstr "该 GPIO 通道不支持切换" + +#: kvmd/apps/kvmd/ugpio.py:61 +msgid "This GPIO channel does not support pulsing" +msgstr "该 GPIO 通道不支持脉冲信号" + +#: kvmd/apps/kvmd/ugpio.py:66 +msgid "Performing another GPIO operation on this channel, please try again later" +msgstr "在此通道上正在执行另一个 GPIO 操作,请稍后再试" + +#: kvmd/apps/kvmd/ugpio.py:204 +#, python-format +msgid "Can't perform %s of %s or operation was not completed: driver offline" +msgstr "无法执行 %s 的 %s 或操作未完成:驱动程序离线" + +#: kvmd/apps/kvmd/ugpio.py:209 +#, python-format +msgid "Ensured switch %s to state=%d" +msgstr "确保将 %s 切换到状态=%d" + +#: kvmd/apps/kvmd/ugpio.py:220 +#, python-format +msgid "Pulsed %s with delay=%.2f" +msgstr "脉冲%s,延迟=%.2f" + +#: kvmd/apps/kvmd/ugpio.py:298 +msgid "Preparing User-GPIO drivers ..." +msgstr "准备 User-GPIO 驱动程序 ......" + +#: kvmd/apps/kvmd/ugpio.py:303 +msgid "Running User-GPIO drivers ..." +msgstr "运行 User-GPIO 驱动程序 ......" + +#: kvmd/apps/kvmd/ugpio.py:314 +#, python-format +msgid "Can't cleanup driver %s" +msgstr "无法清理驱动程序 %s" + +#: kvmd/apps/otg/__init__.py:211 kvmd/plugins/hid/otg/__init__.py:123 +#, python-format +msgid "Using UDC %s" +msgstr "使用 UDC %s" + +#: kvmd/apps/otg/__init__.py:213 +#, python-format +msgid "Creating gadget %r ..." +msgstr "新建 gadget %r ......" + +#: kvmd/apps/otg/__init__.py:254 +msgid "===== Serial =====" +msgstr "===== 串口 =====" + +#: kvmd/apps/otg/__init__.py:258 +msgid "===== Ethernet =====" +msgstr "===== 以太网 =====" + +#: kvmd/apps/otg/__init__.py:262 +msgid "===== HID-Keyboard =====" +msgstr "===== HID-键盘 =====" + +#: kvmd/apps/otg/__init__.py:264 +msgid "===== HID-Mouse =====" +msgstr "===== HID-鼠标 =====" + +#: kvmd/apps/otg/__init__.py:267 +msgid "===== HID-Mouse-Alt =====" +msgstr "===== HID-绝对鼠标 =====" + +#: kvmd/apps/otg/__init__.py:271 +msgid "===== MSD =====" +msgstr "===== MSD =====" + +#: kvmd/apps/otg/__init__.py:275 +#, python-format +msgid "===== MSD Extra: %d =====" +msgstr "===== MSD 扩展: %d =====" + +#: kvmd/apps/otg/__init__.py:278 +msgid "===== Preparing complete =====" +msgstr "===== 准备完成 =====" + +#: kvmd/apps/otg/__init__.py:280 +msgid "Enabling the gadget ..." +msgstr "启用此 gadget ......" + +#: kvmd/apps/otg/__init__.py:286 kvmd/apps/otgnet/__init__.py:128 +msgid "Ready to work" +msgstr "准备就绪" + +#: kvmd/apps/otg/__init__.py:299 +#, python-format +msgid "Disabling gadget %r ..." +msgstr "禁用 gadget %r ......" + +#: kvmd/apps/otgnet/__init__.py:137 +#, python-format +msgid "CMD: %s" +msgstr "命令行: %s" + +#: kvmd/apps/otgnet/__init__.py:150 +#, python-format +msgid "Using IPv4 network %s ..." +msgstr "使用 IPv4 网络 %s ......" + +#: kvmd/apps/otgnet/__init__.py:153 +msgid "Too small network, required at least /31" +msgstr "网络段太小,至少需要 /31" + +#: kvmd/apps/otgnet/__init__.py:173 +#, python-format +msgid "Calculated %r address is %s/%d" +msgstr "计算出的 %r 地址为 %s/%d" + +#: kvmd/apps/otgnet/__init__.py:182 +#, python-format +msgid "Using OTG gadget %r ..." +msgstr "使用 OTG gadget %r ......" + +#: kvmd/apps/otgnet/__init__.py:185 +#, python-format +msgid "Using OTG Ethernet interface %r ..." +msgstr "使用 OTG 以太网接口 %r ......" + +#: kvmd/keyboard/keysym.py:69 +#, python-format +msgid "Invalid modifier key at mapping %s: %s / %s" +msgstr "映射 %s 处的修改键无效: %s / %s" + +#: kvmd/keyboard/keysym.py:122 +#, python-format +msgid "Reading keyboard layout %s ..." +msgstr "读取键盘布局 %s ......" + #: kvmd/plugins/atx/__init__.py:45 msgid "Performing another ATX operation, please try again later" msgstr "正在处理另一个 ATX 动作,请稍等" @@ -188,7 +430,7 @@ msgstr "正在启动 HID 守护程序......" #: kvmd/plugins/hid/bt/__init__.py:182 kvmd/plugins/hid/ch9329/__init__.py:141 msgid "Stopping HID daemon ..." -msgstr "正在启停止 HID 守护程序......" +msgstr "正在停止 HID 守护程序......" #: kvmd/plugins/hid/bt/__init__.py:231 msgid "Unexpected HID error" @@ -197,7 +439,7 @@ msgstr "未知 HID 错误" #: kvmd/plugins/hid/bt/server.py:153 #, python-format msgid "Listening [%s]:%d for %s ..." -msgstr "监听 [%s]:%d for %s ..." +msgstr "监听 [%s]:%d for %s ......" #: kvmd/plugins/hid/bt/server.py:190 #, python-format diff --git a/kvmd/keyboard/keysym.py b/kvmd/keyboard/keysym.py index 5e80d789..1683ad53 100644 --- a/kvmd/keyboard/keysym.py +++ b/kvmd/keyboard/keysym.py @@ -27,6 +27,8 @@ import importlib.machinery import Xlib.keysymdef +from ..lanuages import Lanuages + from ..logging import get_logger from .mappings import At1Key @@ -64,7 +66,7 @@ def build_symmap(path: str) -> dict[int, dict[int, str]]: # x11 keysym -> [(mod or (web_name in WebModifiers.ALTS and key.altgr) or (web_name in WebModifiers.CTRLS and key.ctrl) ): - logger.error("Invalid modifier key at mapping %s: %s / %s", src, web_name, key) + logger.error(Lanuages().gettext("Invalid modifier key at mapping %s: %s / %s"), src, web_name, key) continue modifiers = ( @@ -117,7 +119,7 @@ def _resolve_keysym(name: str) -> int: def _read_keyboard_layout(path: str) -> dict[int, list[At1Key]]: # Keysym to evdev (at1) logger = get_logger(0) - logger.info("Reading keyboard layout %s ...", path) + logger.info(Lanuages().gettext("Reading keyboard layout %s ..."), path) with open(path) as file: lines = list(map(str.strip, file.read().split("\n"))) diff --git a/kvmd/plugins/hid/otg/__init__.py b/kvmd/plugins/hid/otg/__init__.py index 3516546d..202dddca 100644 --- a/kvmd/plugins/hid/otg/__init__.py +++ b/kvmd/plugins/hid/otg/__init__.py @@ -24,6 +24,8 @@ from typing import Iterable from typing import AsyncGenerator from typing import Any +from ....lanuages import Lanuages + from ....logging import get_logger from .... import aiomulti @@ -118,7 +120,7 @@ class Plugin(BaseHid): # pylint: disable=too-many-instance-attributes def sysprep(self) -> None: udc = usb.find_udc(self.__udc) - get_logger(0).info("Using UDC %s", udc) + get_logger(0).info(Lanuages().gettext("Using UDC %s"), udc) self.__keyboard_proc.start(udc) self.__mouse_proc.start(udc) if self.__mouse_alt_proc: diff --git a/message.pot b/message.pot index ff584f26..01bec020 100644 --- a/message.pot +++ b/message.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-08-06 21:57+0800\n" +"POT-Creation-Date: 2024-08-12 22:07+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,6 +17,35 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.15.0\n" +#: kvmd/aiohelpers.py:41 +#, python-format +msgid "Remounting %s storage to %s: %s ..." +msgstr "" + +#: kvmd/aiohelpers.py:48 +#, python-format +msgid "Can't remount %s storage: %s" +msgstr "" + +#: kvmd/aioproc.py:89 +msgid "Asyncio process: too many empty lines" +msgstr "" + +#: kvmd/aioproc.py:104 kvmd/aioproc.py:111 +#, python-format +msgid "Process killed: retcode=%d" +msgstr "" + +#: kvmd/aioproc.py:109 +#, python-format +msgid "Can't kill process pid=%d" +msgstr "" + +#: kvmd/aioproc.py:120 +#, python-format +msgid "Started %s pid=%d" +msgstr "" + #: kvmd/htclient.py:63 msgid "Can't determine filename" msgstr "" @@ -90,58 +119,271 @@ msgstr "" msgid "Make sure you understand exactly what you are doing!" msgstr "" -#: kvmd/apps/kvmd/__init__.py:115 +#: kvmd/apps/kvmd/__init__.py:115 kvmd/apps/otgnet/__init__.py:132 msgid "Bye-bye" msgstr "" -#: kvmd/apps/kvmd/auth.py:57 +#: kvmd/apps/kvmd/auth.py:58 msgid "AUTHORIZATION IS DISABLED" msgstr "" -#: kvmd/apps/kvmd/auth.py:61 +#: kvmd/apps/kvmd/auth.py:62 #, python-format msgid "Authorization is disabled for API %r" msgstr "" -#: kvmd/apps/kvmd/auth.py:66 +#: kvmd/apps/kvmd/auth.py:67 #, python-format msgid "Using internal auth service %r" msgstr "" -#: kvmd/apps/kvmd/auth.py:73 +#: kvmd/apps/kvmd/auth.py:74 #, python-format msgid "Using external auth service %r" msgstr "" -#: kvmd/apps/kvmd/auth.py:101 +#: kvmd/apps/kvmd/auth.py:103 #, python-format msgid "Got access denied for user %r by TOTP" msgstr "" -#: kvmd/apps/kvmd/auth.py:112 +#: kvmd/apps/kvmd/auth.py:114 #, python-format msgid "Authorized user %r via auth service %r" msgstr "" -#: kvmd/apps/kvmd/auth.py:114 +#: kvmd/apps/kvmd/auth.py:116 #, python-format msgid "Got access denied for user %r from auth service %r" msgstr "" -#: kvmd/apps/kvmd/auth.py:124 +#: kvmd/apps/kvmd/auth.py:126 #, python-format msgid "Logged in user %r" msgstr "" -#: kvmd/apps/kvmd/auth.py:134 +#: kvmd/apps/kvmd/auth.py:136 msgid "Can't generate new unique token" msgstr "" -#: kvmd/apps/kvmd/auth.py:145 +#: kvmd/apps/kvmd/auth.py:147 #, python-format msgid "Logged out user %r (%d)" msgstr "" +#: kvmd/apps/kvmd/streamer.py:245 +msgid "Streamer stop cancelled" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:251 +#, python-format +msgid "Waiting %.2f seconds for reset delay ..." +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:253 +msgid "Starting streamer ..." +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:266 kvmd/apps/kvmd/streamer.py:271 +msgid "Stopping streamer immediately ..." +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:280 +msgid "Stopping streamer after delay ..." +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:286 +#, python-format +msgid "Planning to stop streamer in %.2f seconds ..." +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:315 +msgid "Invalid streamer response from /state" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:333 +msgid "Got SIGUSR2, checking the stream state ..." +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:336 +msgid "Installing SIGUSR2 streamer handler ..." +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:392 +msgid "Stream is offline, no signal or so" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:395 +#, python-format +msgid "Can't connect to streamer: %s" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:397 +msgid "Invalid streamer response from /snapshot" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:454 +msgid "Streamer unexpectedly died" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:459 +#, python-format +msgid "Unexpected streamer error: pid=%d" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:461 +msgid "Can't start streamer" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:482 kvmd/apps/otgnet/__init__.py:141 +#, python-format +msgid "Can't execute command: %s" +msgstr "" + +#: kvmd/apps/kvmd/streamer.py:488 +#, python-format +msgid "Started streamer pid=%d: %s" +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:51 +msgid "GPIO channel is not found" +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:56 +msgid "This GPIO channel does not support switching" +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:61 +msgid "This GPIO channel does not support pulsing" +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:66 +msgid "Performing another GPIO operation on this channel, please try again later" +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:204 +#, python-format +msgid "Can't perform %s of %s or operation was not completed: driver offline" +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:209 +#, python-format +msgid "Ensured switch %s to state=%d" +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:220 +#, python-format +msgid "Pulsed %s with delay=%.2f" +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:298 +msgid "Preparing User-GPIO drivers ..." +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:303 +msgid "Running User-GPIO drivers ..." +msgstr "" + +#: kvmd/apps/kvmd/ugpio.py:314 +#, python-format +msgid "Can't cleanup driver %s" +msgstr "" + +#: kvmd/apps/otg/__init__.py:211 kvmd/plugins/hid/otg/__init__.py:123 +#, python-format +msgid "Using UDC %s" +msgstr "" + +#: kvmd/apps/otg/__init__.py:213 +#, python-format +msgid "Creating gadget %r ..." +msgstr "" + +#: kvmd/apps/otg/__init__.py:254 +msgid "===== Serial =====" +msgstr "" + +#: kvmd/apps/otg/__init__.py:258 +msgid "===== Ethernet =====" +msgstr "" + +#: kvmd/apps/otg/__init__.py:262 +msgid "===== HID-Keyboard =====" +msgstr "" + +#: kvmd/apps/otg/__init__.py:264 +msgid "===== HID-Mouse =====" +msgstr "" + +#: kvmd/apps/otg/__init__.py:267 +msgid "===== HID-Mouse-Alt =====" +msgstr "" + +#: kvmd/apps/otg/__init__.py:271 +msgid "===== MSD =====" +msgstr "" + +#: kvmd/apps/otg/__init__.py:275 +#, python-format +msgid "===== MSD Extra: %d =====" +msgstr "" + +#: kvmd/apps/otg/__init__.py:278 +msgid "===== Preparing complete =====" +msgstr "" + +#: kvmd/apps/otg/__init__.py:280 +msgid "Enabling the gadget ..." +msgstr "" + +#: kvmd/apps/otg/__init__.py:286 kvmd/apps/otgnet/__init__.py:128 +msgid "Ready to work" +msgstr "" + +#: kvmd/apps/otg/__init__.py:299 +#, python-format +msgid "Disabling gadget %r ..." +msgstr "" + +#: kvmd/apps/otgnet/__init__.py:137 +#, python-format +msgid "CMD: %s" +msgstr "" + +#: kvmd/apps/otgnet/__init__.py:150 +#, python-format +msgid "Using IPv4 network %s ..." +msgstr "" + +#: kvmd/apps/otgnet/__init__.py:153 +msgid "Too small network, required at least /31" +msgstr "" + +#: kvmd/apps/otgnet/__init__.py:173 +#, python-format +msgid "Calculated %r address is %s/%d" +msgstr "" + +#: kvmd/apps/otgnet/__init__.py:182 +#, python-format +msgid "Using OTG gadget %r ..." +msgstr "" + +#: kvmd/apps/otgnet/__init__.py:185 +#, python-format +msgid "Using OTG Ethernet interface %r ..." +msgstr "" + +#: kvmd/keyboard/keysym.py:69 +#, python-format +msgid "Invalid modifier key at mapping %s: %s / %s" +msgstr "" + +#: kvmd/keyboard/keysym.py:122 +#, python-format +msgid "Reading keyboard layout %s ..." +msgstr "" + #: kvmd/plugins/atx/__init__.py:45 msgid "Performing another ATX operation, please try again later" msgstr ""