From 8b413344e077ec3d8a40ed9411cc2d5e71a609ab Mon Sep 17 00:00:00 2001 From: polyzium Date: Fri, 23 Aug 2024 17:28:50 +0300 Subject: [PATCH 1/4] Add Russian language --- web/src/i18n/index.ts | 3 +- web/src/i18n/ru.ts | 164 ++++++++++++++++++ .../desktop/menu-phone/settings/language.tsx | 1 + .../pages/desktop/menu/settings/language.tsx | 1 + 4 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 web/src/i18n/ru.ts diff --git a/web/src/i18n/index.ts b/web/src/i18n/index.ts index f610389..3c32aa7 100644 --- a/web/src/i18n/index.ts +++ b/web/src/i18n/index.ts @@ -6,8 +6,9 @@ import { getLanguage } from '@/lib/localstorage.ts'; import { en } from './en'; import { fr } from './fr'; import { zh } from './zh'; +import { ru } from './ru'; -const resources = { en, fr, zh }; +const resources = { en, fr, ru, zh }; function getCurrentLanguage(): string { const languages = Object.keys(resources); diff --git a/web/src/i18n/ru.ts b/web/src/i18n/ru.ts new file mode 100644 index 0000000..5b68fba --- /dev/null +++ b/web/src/i18n/ru.ts @@ -0,0 +1,164 @@ +export const ru = { + translation: { + language: 'Язык', + changePassword: 'Изменить пароль', + logout: 'Выйти', + keyboard: 'Клавиатура', + images: 'Образы', + loading: 'Загрузка', + empty: 'Пусто', + settings: 'Настройки', + showMouse: 'Показать мышь', + hideMouse: 'Скрыть мышь', + power: 'Питание', + reset: 'Экстренная перезагрузка', + powerShort: 'Питание (короткое нажатие)', + powerLong: 'Питание (длинное нажатие)', + hddLed: 'Индикатор активности хранилища', + checkLibFailed: 'Не удалось проверить библиотеку среды выполнения, попробуйте еще раз', + updateLibFailed: 'Не удалось обновить библиотеку среды выполнения, попробуйте еще раз', + updatingLib: 'Обновление библиотеки среды выполнения. Пожалуйста, обновите страницу после обновления.', + checkForUpdate: 'Проверить обновления', + head: { + desktop: 'Удаленный рабочий стол', + login: 'Войти', + changePassword: 'Изменить пароль', + terminal: 'Терминал' + }, + auth: { + login: 'Войти', + placeholderUsername: 'Введите имя пользователя', + placeholderPassword: 'Введите пароль', + placeholderPassword2: 'Введите пароль снова', + noEmptyUsername: 'Имя пользователя не может быть пустым', + noEmptyPassword: 'Пароль не может быть пустым', + noAccount: 'Не удалось получить информацию о пользователе, пожалуйста, обновите веб-страницу или сбросьте пароль', + invalidUser: 'Неверное имя пользователя или пароль', + error: 'Непредвиденная ошибка', + changePassword: 'Изменить пароль', + differentPassword: 'Пароли не совпадают', + illegalUsername: 'Имя пользователя содержит недопустимые символы', + illegalPassword: 'Пароль содержит недопустимые символы', + forgetPassword: 'Забыли пароль?', + resetPassword: 'Сбросить пароль', + reset1: 'Если вы забыли пароль, выполните следующие действия для его восстановления:', + reset2: '1. Войдите в устройство NanoKVM по протоколу SSH;', + reset3: '2. Удалите файл на устройстве: ', + reset4: '3. Используйте учетную запись по умолчанию для входа в систему: ', + ok: 'ОК', + cancel: 'Отмена' + }, + screen: { + resolution: 'Разрешение', + fps: 'Частота кадров', + customizeFps: 'Настроить', + quality: 'Качество', + frameDetect: 'Экономия трафика', + frameDetectTip: + "Вычисляет разницу между кадрами и прекращает передачу видеопотока, если на экране удаленного узла не обнаружено никаких изменений." + }, + cursor: { + default: 'Курсор по умолчанию', + pointer: 'Курсор: указатель', + cell: 'Курсор: крест', + text: 'Курсор: выбор текста', + grab: 'Курсор: захват', + hide: 'Скрыть курсор', + mode: 'Режим мыши', + absolute: 'Абсолютный режим', + relative: 'Относительный режим', + requestPointer: 'Используется относительный режим. Нажмите на рабочий стол для захвата мыши.', + resetHid: 'Перезагрузить HID-подсистему' + }, + image: { + title: 'Образы', + loading: 'Загрузка...', + empty: 'Пусто', + tips: { + title: 'Как загрузить', + usb1: 'Подключите NanoKVM к вашему компьютеру через USB.', + usb2: 'Убедитесь что Виртуальный USB-накопитель смонтирован (Настройки - Виртуальный USB-накопитель).', + usb3: 'Откройте виртуальный USB-накопитель на вашем компьютере и скопируйте файл образа в корневую директорию USB-накопителя.', + scp1: 'Убедитесь что NanoKVM и ваш компьютер находятся в одной и той же сети.', + scp2: 'Откройте терминал на вашем компьютере и используйте команду scp чтобы загрузить файл образа в директорию /data, находящуюся на NanoKVM.', + scp3: 'Например: scp путь-к-образу root@ip-вашего-nanokvm:/data', + tfCard: 'Карта памяти', + tf1: 'Этот метод поддерживается на Linux-системах', + tf2: 'Извлеките карту памяти из NanoKVM (если у вас "полная" (Full) версия, сначала нужно разобрать корпус).', + tf3: 'Вставьте карту памяти в картридер и подключите его в свой компьютер.', + tf4: 'Скопируйте файл образа в директорию /data на карте памяти.', + tf5: 'Вставьте карту памяти в NanoKVM.' + }, + }, + script: { + title: 'Скрипты', + upload: 'Загрузить', + run: 'Выполнить', + runBackground: 'Выполнить в фоне', + runFailed: 'Не удалось выполнить', + attention: 'Внимание', + delDesc: 'Вы уверены, что хотите удалить этот файл?', + confirm: 'Да', + cancel: 'Нет', + delete: 'Удалить', + close: 'Закрыть' + }, + terminal: { + title: 'Терминал', + nanokvm: 'Терминал NanoKVM', + serial: 'Терминал COM-порта', + serialPort: 'COM-порт', + serialPortPlaceholder: 'Введите COM-порт', + baudrate: 'Скорость передачи', + confirm: 'ОК' + }, + wol: { + sending: 'Отправка команды...', + sent: 'Команда отправлена', + input: 'Введите MAC-адрес', + ok: 'ОК' + }, + about: { + title: 'О системе NanoKVM', + information: 'Информация', + ip: 'IP-адрес', + mdns: 'Доменное имя mDNS', + firmware: 'Версия ПО', + image: 'Версия прошивки', + deviceKey: 'Ключ устройства', + queryFailed: 'Запрос не удался', + community: 'Сообщество' + }, + update: { + title: 'Проверить обновления', + queryFailed: 'Получить версию не удалось', + updateFailed: 'Обновление не удалось. Пожалуйста, попробуйте еще раз.', + isLatest: 'У вас уже есть последняя версия.', + available: 'Доступно обновление. Вы уверены, что хотите обновить?', + updating: 'Начато обновление. Пожалуйста, подождите...', + confirm: 'Подтвердить', + cancel: 'Отмена' + }, + virtualDevice: { + network: 'Виртуальная сеть', + usb: 'Виртуальный USB-накопитель' + }, + tailscale: { + loading: 'Загрузка...', + notInstalled: 'Tailscale не найден! Пожалуйста, установите.', + install: 'Установить', + installing: 'Установка...', + urlPeriod: 'Этот адрес действителен в течение 10 минут', + installed: 'Tailscale уже установлен. Пожалуйста, войдите в систему.', + login: 'Войти', + failed: 'Не удалось установить', + retry: 'Пожалуйста, обновите и попробуйте снова, или попробуйте установить вручную', + download: 'Скачайте', + package: 'установочный пакет', + unzip: 'и разархивируйте его', + upTailscale: 'Переместите tailscale в каталог /usr/bin/ на NanoKVM', + upTailscaled: 'Переместите tailscaled в каталог /usr/sbin/ на NanoKVM', + refresh: 'Обновите текущую страницу' + } + } +}; diff --git a/web/src/pages/desktop/menu-phone/settings/language.tsx b/web/src/pages/desktop/menu-phone/settings/language.tsx index 511c936..c708663 100644 --- a/web/src/pages/desktop/menu-phone/settings/language.tsx +++ b/web/src/pages/desktop/menu-phone/settings/language.tsx @@ -18,6 +18,7 @@ export const Language = () => { const languageItems = [ { lng: 'en', name: 'English' }, { lng: 'fr', name: 'Français' }, + { lng: 'ru', name: 'Русский' }, { lng: 'zh', name: '中文' } ]; diff --git a/web/src/pages/desktop/menu/settings/language.tsx b/web/src/pages/desktop/menu/settings/language.tsx index 511c936..c708663 100644 --- a/web/src/pages/desktop/menu/settings/language.tsx +++ b/web/src/pages/desktop/menu/settings/language.tsx @@ -18,6 +18,7 @@ export const Language = () => { const languageItems = [ { lng: 'en', name: 'English' }, { lng: 'fr', name: 'Français' }, + { lng: 'ru', name: 'Русский' }, { lng: 'zh', name: '中文' } ]; From 655227e270d3e979b3f65bffeb730faed6ab1e76 Mon Sep 17 00:00:00 2001 From: polyzium Date: Fri, 23 Aug 2024 17:28:50 +0300 Subject: [PATCH 2/4] Add generic 104 key layout for virtual kbd --- web/src/assets/styles/keyboard.css | 10 ++++--- web/src/pages/desktop/keyboard/mappings.ts | 2 ++ .../desktop/keyboard/virtual-keyboard.tsx | 24 ++++++++++++++++- .../pages/desktop/keyboard/virtual-keys.ts | 26 +++++++++++++++---- 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/web/src/assets/styles/keyboard.css b/web/src/assets/styles/keyboard.css index 6db01f5..7ec4d6c 100644 --- a/web/src/assets/styles/keyboard.css +++ b/web/src/assets/styles/keyboard.css @@ -79,18 +79,22 @@ box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); } -.hg-button.hg-functionBtn.hg-button-space { +.hg-layout-default .hg-button.hg-functionBtn.hg-button-space { + width: 250px; +} + +.hg-layout-mac .hg-button.hg-functionBtn.hg-button-space { width: 350px; } -.simple-keyboard.hg-layout-default .hg-button.hg-highlight { +.simple-keyboard.hg-layout-default .simple-keyboard.hg-layout-mac .hg-button.hg-highlight { background: rgb(37 99 235); border-bottom: 1px solid #2563eb; box-shadow: 0 1px 3px 0 rgb(37 99 235 / 0.1), 0 1px 2px -1px rgb(37 99 235 / 0.1); color: white; } -.simple-keyboard.hg-layout-default .hg-button.hg-double{ +.simple-keyboard.hg-layout-default .simple-keyboard.hg-layout-mac .hg-button.hg-double{ text-align: center; font-size: 14px; line-height: 16px; diff --git a/web/src/pages/desktop/keyboard/mappings.ts b/web/src/pages/desktop/keyboard/mappings.ts index 5cb46ff..f4f6b36 100644 --- a/web/src/pages/desktop/keyboard/mappings.ts +++ b/web/src/pages/desktop/keyboard/mappings.ts @@ -106,6 +106,8 @@ export const KeyboardCodes: Map = new Map([ ['NumpadDecimal', 99], ['KeyKpDot', 99], + ['Menu', 118], + ['ControlLeft', 224], ['ShiftLeft', 225], ['AltLeft', 226], diff --git a/web/src/pages/desktop/keyboard/virtual-keyboard.tsx b/web/src/pages/desktop/keyboard/virtual-keyboard.tsx index 67a1540..ccd7876 100644 --- a/web/src/pages/desktop/keyboard/virtual-keyboard.tsx +++ b/web/src/pages/desktop/keyboard/virtual-keyboard.tsx @@ -4,6 +4,8 @@ import { useAtom } from 'jotai'; import { XIcon } from 'lucide-react'; import Keyboard, { KeyboardButtonTheme } from 'react-simple-keyboard'; import { Drawer } from 'vaul'; +import { Radio } from 'antd'; +import type { RadioChangeEvent } from 'antd'; import 'react-simple-keyboard/build/css/index.css'; import '@/assets/styles/keyboard.css'; @@ -25,11 +27,17 @@ type KeyboardProps = { isBigScreen: boolean; }; +const keyboardLayoutOptions = [ + { label: 'Win', value: 'default' }, + { label: 'Mac', value: 'mac' } +]; + export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => { const [isKeyboardOpen, setIsKeyboardOpen] = useAtom(isKeyboardOpenAtom); const [isCapsLock, setIsCapsLock] = useState(false); const [activeModifierKeys, setActiveModifierKeys] = useState([]); + const [layout, setLayout] = useState('default'); const keyboardRef = useRef(null); @@ -126,6 +134,10 @@ export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => { return theme; } + function selectLayout({ target: { value } }: RadioChangeEvent) { + setLayout(value); + } + return ( @@ -137,7 +149,16 @@ export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => { > {/* header */}
-
Keyboard
+
+
Keyboard
+ +
{ keyboardRef={(r) => (keyboardRef.current = r)} onKeyPress={onKeyPress} onKeyReleased={onKeyReleased} + layoutName={layout} {...keyboardOptions} /> diff --git a/web/src/pages/desktop/keyboard/virtual-keys.ts b/web/src/pages/desktop/keyboard/virtual-keys.ts index 65d6427..20e38d5 100644 --- a/web/src/pages/desktop/keyboard/virtual-keys.ts +++ b/web/src/pages/desktop/keyboard/virtual-keys.ts @@ -1,9 +1,17 @@ // main keys export const keyboardOptions = { - theme: 'simple-keyboard hg-theme-default hg-layout-default', + theme: 'simple-keyboard hg-theme-default', baseClass: 'simple-keyboard-main', layout: { default: [ + '{escape} F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12', + 'Backquote Digit1 Digit2 Digit3 Digit4 Digit5 Digit6 Digit7 Digit8 Digit9 Digit0 Minus Equal {backspace}', + '{tab} KeyQ KeyW KeyE KeyR KeyT KeyY KeyU KeyI KeyO KeyP BracketLeft BracketRight Backslash', + '{capslock} KeyA KeyS KeyD KeyF KeyG KeyH KeyJ KeyK KeyL Semicolon Quote {enter}', + '{shiftleft} KeyZ KeyX KeyC KeyV KeyB KeyN KeyM Comma Period Slash {shiftright}', + '{controlleft} {winleft} {altleft} {space} {altright} {winright} {menu} {controlright}' + ], + mac: [ '{escape} F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12', 'Backquote Digit1 Digit2 Digit3 Digit4 Digit5 Digit6 Digit7 Digit8 Digit9 Digit0 Minus Equal {backspace}', '{tab} KeyQ KeyW KeyE KeyR KeyT KeyY KeyU KeyI KeyO KeyP BracketLeft BracketRight Backslash', @@ -74,15 +82,19 @@ export const keyboardOptions = { '{controlleft}': 'Ctrl', '{altleft}': 'Alt', '{metaleft}': 'Cmd', + '{winleft}': 'Win', '{space}': 'Space', '{metaright}': 'Cmd', - '{altright}': 'Alt' + '{winright}': 'Win', + '{altright}': 'Alt', + '{menu}': "Menu", + '{controlright}': 'Ctrl', } }; // control keys export const keyboardControlPadOptions = { - theme: 'simple-keyboard hg-theme-default hg-layout-default', + theme: 'simple-keyboard hg-theme-default', baseClass: 'simple-keyboard-control', layout: { default: [ @@ -107,7 +119,7 @@ export const keyboardControlPadOptions = { // arrow keys export const keyboardArrowsOptions = { - theme: 'simple-keyboard hg-theme-default hg-layout-default', + theme: 'simple-keyboard hg-theme-default', baseClass: 'simple-keyboard-arrows', layout: { default: ['{arrowup}', '{arrowleft} {arrowdown} {arrowright}'] @@ -126,8 +138,10 @@ export const specialKeyMap = new Map([ ['{controlleft}', 'ControlLeft'], ['{altleft}', 'AltLeft'], ['{metaleft}', 'MetaLeft'], + ['{winleft}', 'WinLeft'], ['{space}', 'Space'], ['{metaright}', 'MetaRight'], + ['{winright}', 'WinRight'], ['{altright}', 'AltRight'], ['{prtscr}', 'PrintScreen'], ['{scrolllock}', 'ScrollLock'], @@ -150,10 +164,12 @@ export const modifierKeys = [ '{controlleft}', '{altleft}', '{metaleft}', + '{winleft}', '{shiftright}', '{controlright}', '{altright}', - '{metaright}' + '{metaright}', + '{winright}' ]; // double line display buttons From 62e8ab2ac806ab2da002e16814b969aeb6aa4379 Mon Sep 17 00:00:00 2001 From: polyzium Date: Fri, 23 Aug 2024 17:28:50 +0300 Subject: [PATCH 3/4] Translate "Keyboard" in the kbd header bar --- web/src/pages/desktop/keyboard/virtual-keyboard.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/src/pages/desktop/keyboard/virtual-keyboard.tsx b/web/src/pages/desktop/keyboard/virtual-keyboard.tsx index ccd7876..8d54233 100644 --- a/web/src/pages/desktop/keyboard/virtual-keyboard.tsx +++ b/web/src/pages/desktop/keyboard/virtual-keyboard.tsx @@ -6,6 +6,7 @@ import Keyboard, { KeyboardButtonTheme } from 'react-simple-keyboard'; import { Drawer } from 'vaul'; import { Radio } from 'antd'; import type { RadioChangeEvent } from 'antd'; +import { useTranslation } from 'react-i18next'; import 'react-simple-keyboard/build/css/index.css'; import '@/assets/styles/keyboard.css'; @@ -33,6 +34,8 @@ const keyboardLayoutOptions = [ ]; export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => { + const { t } = useTranslation(); + const [isKeyboardOpen, setIsKeyboardOpen] = useAtom(isKeyboardOpenAtom); const [isCapsLock, setIsCapsLock] = useState(false); @@ -150,7 +153,9 @@ export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => { {/* header */}
-
Keyboard
+
+ {t('keyboard')} +
Date: Fri, 23 Aug 2024 17:28:50 +0300 Subject: [PATCH 4/4] Fix font in the keyboard header --- web/src/assets/styles/keyboard.css | 4 ++++ web/src/pages/desktop/keyboard/virtual-keyboard.tsx | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/web/src/assets/styles/keyboard.css b/web/src/assets/styles/keyboard.css index 7ec4d6c..59497ce 100644 --- a/web/src/assets/styles/keyboard.css +++ b/web/src/assets/styles/keyboard.css @@ -99,3 +99,7 @@ font-size: 14px; line-height: 16px; } + +.keyboard-header { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} diff --git a/web/src/pages/desktop/keyboard/virtual-keyboard.tsx b/web/src/pages/desktop/keyboard/virtual-keyboard.tsx index 8d54233..322c253 100644 --- a/web/src/pages/desktop/keyboard/virtual-keyboard.tsx +++ b/web/src/pages/desktop/keyboard/virtual-keyboard.tsx @@ -153,7 +153,7 @@ export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => { {/* header */}
-
+
{t('keyboard')}