From cee8d6427c8ac5e8f009f807fe110048c9178ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Severin=20M=C3=BCller?= Date: Sat, 1 Nov 2025 14:41:07 +0100 Subject: [PATCH] Add localization --- serial.go | 2 + ui/localization/messages/en.json | 26 +++++ ui/src/components/Terminal.tsx | 5 +- .../components/extensions/SerialConsole.tsx | 109 +++++++++--------- 4 files changed, 82 insertions(+), 60 deletions(-) diff --git a/serial.go b/serial.go index d61f9108..68c3ba20 100644 --- a/serial.go +++ b/serial.go @@ -285,7 +285,9 @@ var serialConfig = SerialSettings{ EnableEcho: false, NormalizeMode: "names", NormalizeLineEnd: "keep", + TabRender: "", PreserveANSI: true, + ShowNLTag: false, Buttons: []QuickButton{}, } diff --git a/ui/localization/messages/en.json b/ui/localization/messages/en.json index 0356e8e5..8f4e8d73 100644 --- a/ui/localization/messages/en.json +++ b/ui/localization/messages/en.json @@ -718,10 +718,26 @@ "saving": "Saving…", "search_placeholder": "Search…", "serial_console": "Serial Console", + "serial_console_add_button": "Add Button", "serial_console_baud_rate": "Baud Rate", + "serial_console_button_editor_command": "Command", + "serial_console_button_editor_command_placeholder": "Command to send", + "serial_console_button_editor_delete": "Delete", + "serial_console_button_editor_explanation": "When sent, the selected line ending {terminator} will be appended.", + "serial_console_button_editor_label": "Label", + "serial_console_button_editor_label_placeholder": "New Command", + "serial_console_button_editor_move_down": "Move Down", + "serial_console_button_editor_move_up": "Move Up", "serial_console_configure_description": "Configure your serial console settings", + "serial_console_crlf_handling": "CRLF Handling", "serial_console_data_bits": "Data Bits", "serial_console_get_settings_error": "Failed to get serial console settings: {error}", + "serial_console_hide_settings": "Hide Settings", + "serial_console_line_ending": "Line Ending", + "serial_console_line_ending_explanation": "Character(s) sent at the end of each command", + "serial_console_local_echo": "Local Echo", + "serial_console_local_echo_description": "Show characters you type in the console", + "serial_console_normalization_mode": "Normalization Mode", "serial_console_open_console": "Open Console", "serial_console_parity": "Parity", "serial_console_parity_even": "Even Parity", @@ -729,8 +745,18 @@ "serial_console_parity_none": "No Parity", "serial_console_parity_odd": "Odd Parity", "serial_console_parity_space": "Space Parity", + "serial_console_preserve_ansi": "Preserve ANSI", + "serial_console_preserve_ansi_keep": "Keep escape code", + "serial_console_preserve_ansi_strip": "Strip escape code", + "serial_console_send_custom_command": "Failed to send custom command: {command}: {error}", "serial_console_set_settings_error": "Failed to set serial console settings to {settings}: {error}", + "serial_console_show_newline_tag": "Show newline tag", + "serial_console_show_newline_tag_hide": "Hide tag", + "serial_console_show_newline_tag_show": "Show tag", + "serial_console_show_settings": "Show Settings", "serial_console_stop_bits": "Stop Bits", + "serial_console_tab_replacement": "Tab replacement", + "serial_console_tab_replacement_description": "Empty for no replacement", "setting_remote_description": "Setting remote description", "setting_remote_session_description": "Setting remote session description...", "setting_up_connection_to_device": "Setting up connection to device...", diff --git a/ui/src/components/Terminal.tsx b/ui/src/components/Terminal.tsx index c397a540..90f2a94d 100644 --- a/ui/src/components/Terminal.tsx +++ b/ui/src/components/Terminal.tsx @@ -8,16 +8,13 @@ import { WebglAddon } from "@xterm/addon-webgl"; import { Unicode11Addon } from "@xterm/addon-unicode11"; import { ClipboardAddon } from "@xterm/addon-clipboard"; +import { m } from "@localizations/messages.js"; import { cx } from "@/cva.config"; import { AvailableTerminalTypes, useUiStore, useTerminalStore } from "@/hooks/stores"; import { CommandInput } from "@/components/CommandInput"; import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc"; import notifications from "@/notifications"; - -import { Button } from "./Button"; import { Button } from "@components/Button"; -import { m } from "@localizations/messages.js"; - const isWebGl2Supported = !!document.createElement("canvas").getContext("webgl2"); diff --git a/ui/src/components/extensions/SerialConsole.tsx b/ui/src/components/extensions/SerialConsole.tsx index 3f22cac0..8a7e2cc6 100644 --- a/ui/src/components/extensions/SerialConsole.tsx +++ b/ui/src/components/extensions/SerialConsole.tsx @@ -1,12 +1,9 @@ import { LuPlus, LuTrash2, LuPencil, LuSettings2, LuEye, LuEyeOff, LuSave, LuArrowBigUp, LuArrowBigDown, LuCircleX, LuTerminal } from "react-icons/lu"; import { useEffect, useMemo, useState } from "react"; -import { m } from "@localizations/messages.js"; import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc"; -import { useUiStore } from "@hooks/stores"; import { Button } from "@components/Button"; import Card from "@components/Card"; -import { SelectMenuBasic } from "@components/SelectMenuBasic"; import { SettingsPageHeader } from "@components/SettingsPageheader"; import notifications from "@/notifications"; import { SelectMenuBasic } from "@components/SelectMenuBasic"; @@ -14,7 +11,7 @@ import { InputFieldWithLabel } from "@components/InputField"; import { useUiStore, useTerminalStore } from "@/hooks/stores"; import Checkbox from "@components/Checkbox"; import {SettingsItem} from "@components/SettingsItem"; - +import { m } from "@localizations/messages.js"; /** ============== Types ============== */ @@ -51,7 +48,7 @@ export function SerialConsole() { const { send } = useJsonRpc(); // extension config (buttons + prefs) - const [buttonConfig, setButtonConfig] = useState({ + const [settings, setSettings] = useState({ baudRate: 9600, dataBits: 8, stopBits: "1", @@ -89,21 +86,21 @@ export function SerialConsole() { return; } - setButtonConfig(resp.result as SerialSettings); + setSettings(resp.result as SerialSettings); setTerminator((resp.result as SerialSettings).terminator.value); }); }, [send, setTerminator]); const handleSerialSettingsChange = (config: keyof SerialSettings, value: unknown) => { - const newButtonConfig = { ...buttonConfig, [config]: value }; - send("setSerialSettings", { settings: newButtonConfig }, (resp: JsonRpcResponse) => { + const newSettings = { ...settings, [config]: value }; + send("setSerialSettings", { settings: newSettings }, (resp: JsonRpcResponse) => { if ("error" in resp) { - notifications.error(`Failed to update serial settings: ${resp.error.data || "Unknown error"}`); + notifications.error(m.serial_console_set_settings_error({ settings: newSettings, error: resp.error.data || m.unknown_error() })); return; } }); - setButtonConfig(newButtonConfig); + setSettings(newSettings); }; const onClickButton = (btn: QuickButton) => { @@ -112,7 +109,7 @@ export function SerialConsole() { send("sendCustomCommand", { command }, (resp: JsonRpcResponse) => { if ("error" in resp) { - notifications.error(m.serial_console_set_settings_error({ settings: setting, error: resp.error.data || m.unknown_error() })); + notifications.error(m.serial_console_send_custom_command({ command: command, error: resp.error.data || m.unknown_error() })); return; } }); @@ -134,14 +131,14 @@ export function SerialConsole() { }; const removeBtn = (id: string) => { - const nextButtons = buttonConfig.buttons.filter(b => b.id !== id).map((b, i) => ({ ...b, sort: i })) ; + const nextButtons = settings.buttons.filter(b => b.id !== id).map((b, i) => ({ ...b, sort: i })) ; handleSerialSettingsChange("buttons", stableSort(nextButtons) ); setEditorOpen(null); }; const moveUpBtn = (id: string) => { // Make a copy so we don't mutate state directly - const newButtons = [...buttonConfig.buttons]; + const newButtons = [...settings.buttons]; // Find the index of the button to move const index = newButtons.findIndex(b => b.id === id); @@ -162,7 +159,7 @@ export function SerialConsole() { const moveDownBtn = (id: string) => { // Make a copy so we don't mutate state directly - const newButtons = [...buttonConfig.buttons]; + const newButtons = [...settings.buttons]; // Find the index of the button to move const index = newButtons.findIndex(b => b.id === id); @@ -199,15 +196,15 @@ export function SerialConsole() { // if new, assign next sort index // if existing, keep sort index const nextButtons = currentID - ? buttonConfig.buttons.map(b => (b.id === currentID ? { ...b, label, command , terminator} : b)) - : [...buttonConfig.buttons, { id: genId(), label, command, terminator, sort: buttonConfig.buttons.length }]; + ? settings.buttons.map(b => (b.id === currentID ? { ...b, label, command , terminator} : b)) + : [...settings.buttons, { id: genId(), label, command, terminator, sort: settings.buttons.length }]; handleSerialSettingsChange("buttons", stableSort(nextButtons) ); setEditorOpen(null); }; /** simple reordering: alphabetical by sort, then label */ - const sortedButtons = useMemo(() => buttonConfig.buttons, [buttonConfig.buttons]); + const sortedButtons = useMemo(() => settings.buttons, [settings.buttons]); return (
@@ -223,15 +220,15 @@ export function SerialConsole() {