diff --git a/ui/localization/jetKVM.UI.inlang/settings.json b/ui/localization/jetKVM.UI.inlang/settings.json index efe14c88..2aa828df 100644 --- a/ui/localization/jetKVM.UI.inlang/settings.json +++ b/ui/localization/jetKVM.UI.inlang/settings.json @@ -31,9 +31,17 @@ "plugin.inlang.messageFormat": { "pathPattern": "./messages/{locale}.json" }, + "plugin.inlang.mFunctionMatcher": { + "matchers": [ + { + "type": "m-function", + "function": "plural", + "parameter": "count" + } + ] + }, "strategy": [ "cookie", - "localStorage", "preferredLanguage", "baseLocale" ] diff --git a/ui/localization/messages/da.json b/ui/localization/messages/da.json index ddb6c5d6..0ee112ec 100644 --- a/ui/localization/messages/da.json +++ b/ui/localization/messages/da.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "Du har ændret din adgangskode til beskyttelse af din lokale enhed. Husk din nye adgangskode til senere brug.", "local_auth_success_password_updated_title": "Adgangskode opdateret", "local_auth_update_password_button": "Opdater adgangskode", + "locale_auto": "Bil", + "locale_change_success": "Sproget er ændret til {locale}", + "locale_da": "Dansk", + "locale_de": "Tysk", + "locale_en": "Engelsk", + "locale_es": "Spansk", + "locale_fr": "Fransk", + "locale_it": "Italiensk", + "locale_nb": "Norsk (bokmål)", + "locale_sv": "Svensk", + "locale_zh": "中文 (简体)", "log_in": "Log ind", "log_out": "Log ud", "logged_in_as": "Logget ind som", @@ -748,6 +759,8 @@ "usb_state_disconnected": "Afbrudt", "usb_state_low_power_mode": "Lavstrømstilstand", "usb": "USB", + "user_interface_language_description": "Vælg det sprog, der skal bruges i JetKVM-brugergrænsefladen", + "user_interface_language_title": "Grænsefladesprog", "video_brightness_description": "Lysstyrkeniveau ( {value} x)", "video_brightness_title": "Lysstyrke", "video_contrast_description": "Kontrastniveau ( {value} x)", diff --git a/ui/localization/messages/de.json b/ui/localization/messages/de.json index 503e764a..ccc5e6b7 100644 --- a/ui/localization/messages/de.json +++ b/ui/localization/messages/de.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "Sie haben Ihr lokales Geräteschutzkennwort erfolgreich geändert. Merken Sie sich das neue Kennwort für zukünftige Zugriffe.", "local_auth_success_password_updated_title": "Passwort erfolgreich aktualisiert", "local_auth_update_password_button": "Kennwort aktualisieren", + "locale_auto": "Auto", + "locale_change_success": "Die Sprache wurde erfolgreich in {locale} geändert.", + "locale_da": "Dänisch", + "locale_de": "Deutsch", + "locale_en": "Englisch", + "locale_es": "Spanisch", + "locale_fr": "Deutsch", + "locale_it": "Italienisch", + "locale_nb": "Norwegisch (bokmål)", + "locale_sv": "Schwedisch", + "locale_zh": "中文 (简体)", "log_in": "Einloggen", "log_out": "Ausloggen", "logged_in_as": "Angemeldet als", @@ -748,6 +759,8 @@ "usb_state_disconnected": "Getrennt", "usb_state_low_power_mode": "Energiesparmodus", "usb": "USB", + "user_interface_language_description": "Wählen Sie die Sprache aus, die in der JetKVM-Benutzeroberfläche verwendet werden soll", + "user_interface_language_title": "Schnittstellensprache", "video_brightness_description": "Helligkeitsstufe ( {value} x)", "video_brightness_title": "Helligkeit", "video_contrast_description": "Kontraststufe ( {value} x)", diff --git a/ui/localization/messages/en.json b/ui/localization/messages/en.json index 1692f5fb..428a9ada 100644 --- a/ui/localization/messages/en.json +++ b/ui/localization/messages/en.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "You've successfully changed your local device protection password. Make sure to remember your new password for future access.", "local_auth_success_password_updated_title": "Password Updated Successfully", "local_auth_update_password_button": "Update Password", + "locale_auto": "Auto", + "locale_change_success": "Language changed successfully to {locale}", + "locale_da": "Dansk", + "locale_de": "Deutsch", + "locale_en": "English", + "locale_es": "Español", + "locale_fr": "Français", + "locale_it": "Italiano", + "locale_nb": "Norsk (bokmål)", + "locale_sv": "Svenska", + "locale_zh": "中文 (简体)", "log_in": "Log In", "log_out": "Log out", "logged_in_as": "Logged in as", @@ -748,6 +759,8 @@ "usb_state_disconnected": "Disconnected", "usb_state_low_power_mode": "Low power mode", "usb": "USB", + "user_interface_language_description": "Select the language to use in the JetKVM user interface", + "user_interface_language_title": "Interface Language", "video_brightness_description": "Brightness level ({value}x)", "video_brightness_title": "Brightness", "video_contrast_description": "Contrast level ({value}x)", diff --git a/ui/localization/messages/es.json b/ui/localization/messages/es.json index c7fa5922..d1e506c3 100644 --- a/ui/localization/messages/es.json +++ b/ui/localization/messages/es.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "Has cambiado correctamente la contraseña de protección de tu dispositivo local. Recuerda la nueva contraseña para acceder en el futuro.", "local_auth_success_password_updated_title": "Contraseña actualizada exitosamente", "local_auth_update_password_button": "Actualizar contraseña", + "locale_auto": "Auto", + "locale_change_success": "El idioma se cambió correctamente a {locale}", + "locale_da": "Danés", + "locale_de": "Alemán", + "locale_en": "Inglés", + "locale_es": "Español", + "locale_fr": "Francés", + "locale_it": "Italiano", + "locale_nb": "Noruego (bokmål)", + "locale_sv": "Sueco", + "locale_zh": "中文 (简体)", "log_in": "Acceso", "log_out": "Finalizar la sesión", "logged_in_as": "Inició sesión como", @@ -748,6 +759,8 @@ "usb_state_disconnected": "Desconectado", "usb_state_low_power_mode": "Modo de bajo consumo", "usb": "USB", + "user_interface_language_description": "Seleccione el idioma que se utilizará en la interfaz de usuario de JetKVM", + "user_interface_language_title": "Lenguaje de interfaz", "video_brightness_description": "Nivel de brillo ( {value} x)", "video_brightness_title": "Brillo", "video_contrast_description": "Nivel de contraste ( {value} x)", diff --git a/ui/localization/messages/fr.json b/ui/localization/messages/fr.json index e58862ce..e9fcf034 100644 --- a/ui/localization/messages/fr.json +++ b/ui/localization/messages/fr.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "Vous avez modifié avec succès le mot de passe de protection de votre appareil local. N'oubliez pas de le mémoriser pour y accéder ultérieurement.", "local_auth_success_password_updated_title": "Mot de passe mis à jour avec succès", "local_auth_update_password_button": "Mettre à jour le mot de passe", + "locale_auto": "Auto", + "locale_change_success": "La langue a été modifiée avec succès en {locale}", + "locale_da": "danois", + "locale_de": "Allemand", + "locale_en": "Anglais", + "locale_es": "Espagnol", + "locale_fr": "Français", + "locale_it": "italien", + "locale_nb": "Norvégien (bokmål)", + "locale_sv": "suédois", + "locale_zh": "中文 (简体)", "log_in": "Se connecter", "log_out": "Se déconnecter", "logged_in_as": "Connecté en tant que", @@ -748,6 +759,8 @@ "usb_state_disconnected": "Déconnecté", "usb_state_low_power_mode": "Mode basse consommation", "usb": "USB", + "user_interface_language_description": "Sélectionnez la langue à utiliser dans l'interface utilisateur de JetKVM", + "user_interface_language_title": "Langue de l'interface", "video_brightness_description": "Niveau de luminosité ( {value} x)", "video_brightness_title": "Luminosité", "video_contrast_description": "Niveau de contraste ( {value} x)", diff --git a/ui/localization/messages/it.json b/ui/localization/messages/it.json index 7bb80363..319a7ae1 100644 --- a/ui/localization/messages/it.json +++ b/ui/localization/messages/it.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "Hai modificato correttamente la password di protezione del tuo dispositivo locale. Assicurati di ricordare la nuova password per gli accessi futuri.", "local_auth_success_password_updated_title": "Password aggiornata con successo", "local_auth_update_password_button": "Aggiorna password", + "locale_auto": "Auto", + "locale_change_success": "Lingua modificata correttamente in {locale}", + "locale_da": "Danese", + "locale_de": "Tedesco", + "locale_en": "Inglese", + "locale_es": "Spagnolo", + "locale_fr": "Francese", + "locale_it": "Italiano", + "locale_nb": "Norvegese (bokmål)", + "locale_sv": "Svedese", + "locale_zh": "中文 (简体)", "log_in": "Login", "log_out": "Disconnetti", "logged_in_as": "Accedi come", @@ -748,6 +759,8 @@ "usb_state_disconnected": "Disconnesso", "usb_state_low_power_mode": "Modalità a basso consumo", "usb": "USB", + "user_interface_language_description": "Seleziona la lingua da utilizzare nell'interfaccia utente JetKVM", + "user_interface_language_title": "Lingua dell'interfaccia", "video_brightness_description": "Livello di luminosità ( {value} x)", "video_brightness_title": "Luminosità", "video_contrast_description": "Livello di contrasto ( {value} x)", diff --git a/ui/localization/messages/nb.json b/ui/localization/messages/nb.json index 6a517397..7a78bff6 100644 --- a/ui/localization/messages/nb.json +++ b/ui/localization/messages/nb.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "Du har endret passordet for beskyttelse av den lokale enheten. Husk det nye passordet for fremtidig tilgang.", "local_auth_success_password_updated_title": "Passord oppdatert", "local_auth_update_password_button": "Oppdater passord", + "locale_auto": "Bil", + "locale_change_success": "Språket er endret til {locale}", + "locale_da": "Dansk", + "locale_de": "Tysk", + "locale_en": "Engelsk", + "locale_es": "Spansk", + "locale_fr": "Fransk", + "locale_it": "Italiensk", + "locale_nb": "Norsk (bokmål)", + "locale_sv": "Svensk", + "locale_zh": "中文 (简体)", "log_in": "Logg inn", "log_out": "Logg ut", "logged_in_as": "Logget inn som", @@ -748,6 +759,8 @@ "usb_state_disconnected": "Frakoblet", "usb_state_low_power_mode": "Lavstrømsmodus", "usb": "USB", + "user_interface_language_description": "Velg språket som skal brukes i JetKVM-brukergrensesnittet", + "user_interface_language_title": "Grensesnittspråk", "video_brightness_description": "Lysstyrkenivå ( {value} x)", "video_brightness_title": "Lysstyrke", "video_contrast_description": "Kontrastnivå ( {value} x)", diff --git a/ui/localization/messages/sv.json b/ui/localization/messages/sv.json index c4bda6af..196c84e8 100644 --- a/ui/localization/messages/sv.json +++ b/ui/localization/messages/sv.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "Du har ändrat ditt lösenord för lokal enhetsskydd. Se till att komma ihåg ditt nya lösenord för framtida åtkomst.", "local_auth_success_password_updated_title": "Lösenordet har uppdaterats", "local_auth_update_password_button": "Uppdatera lösenord", + "locale_auto": "Bil", + "locale_change_success": "Språket har ändrats till {locale}", + "locale_da": "Danska", + "locale_de": "Deutsch", + "locale_en": "Engelska", + "locale_es": "Spanska", + "locale_fr": "Franska", + "locale_it": "italiensk", + "locale_nb": "Norska (bokmål)", + "locale_sv": "Svenska", + "locale_zh": "中文 (简体)", "log_in": "Logga in", "log_out": "Logga ut", "logged_in_as": "Inloggad som", @@ -748,6 +759,8 @@ "usb_state_disconnected": "Osammanhängande", "usb_state_low_power_mode": "Lågströmsläge", "usb": "USB", + "user_interface_language_description": "Välj språket som ska användas i JetKVM-användargränssnittet", + "user_interface_language_title": "Gränssnittsspråk", "video_brightness_description": "Ljusstyrka ( {value} x)", "video_brightness_title": "Ljusstyrka", "video_contrast_description": "Kontrastnivå ( {value} x)", diff --git a/ui/localization/messages/zh.json b/ui/localization/messages/zh.json index d817deea..dd5ef301 100644 --- a/ui/localization/messages/zh.json +++ b/ui/localization/messages/zh.json @@ -395,6 +395,17 @@ "local_auth_success_password_updated_description": "您已成功更改本地设备保护密码。请务必记住新密码,以便日后访问。", "local_auth_success_password_updated_title": "密码更新成功", "local_auth_update_password_button": "更新密码", + "locale_auto": "汽车", + "locale_change_success": "语言已成功更改为{locale}", + "locale_da": "丹麦语", + "locale_de": "德语", + "locale_en": "英语", + "locale_es": "西班牙语", + "locale_fr": "法语", + "locale_it": "意大利语", + "locale_nb": "挪威语(博克马尔语)", + "locale_sv": "瑞典语", + "locale_zh": "中文 (简体)", "log_in": "登录", "log_out": "登出", "logged_in_as": "登录身份", @@ -748,6 +759,8 @@ "usb_state_disconnected": "断开连接", "usb_state_low_power_mode": "低功耗模式", "usb": "USB", + "user_interface_language_description": "选择 JetKVM 用户界面使用的语言", + "user_interface_language_title": "界面语言", "video_brightness_description": "亮度级别( {value} x)", "video_brightness_title": "亮度", "video_contrast_description": "对比度级别( {value} x)", diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index cad434d4..0eae3479 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -244,6 +244,7 @@ export interface MouseMove { y: number; buttons: number; } + export interface MouseState { mouseX: number; mouseY: number; @@ -347,8 +348,10 @@ export interface SettingsState { // Video enhancement settings videoSaturation: number; setVideoSaturation: (value: number) => void; + videoBrightness: number; setVideoBrightness: (value: number) => void; + videoContrast: number; setVideoContrast: (value: number) => void; } @@ -392,8 +395,10 @@ export const useSettingsStore = create( // Video enhancement settings with default values (1.0 = normal) videoSaturation: 1.0, setVideoSaturation: (value: number) => set({ videoSaturation: value }), + videoBrightness: 1.0, setVideoBrightness: (value: number) => set({ videoBrightness: value }), + videoContrast: 1.0, setVideoContrast: (value: number) => set({ videoContrast: value }), }), diff --git a/ui/src/routes/devices.$id.settings.general._index.tsx b/ui/src/routes/devices.$id.settings.general._index.tsx index cca18c03..86a6981c 100644 --- a/ui/src/routes/devices.$id.settings.general._index.tsx +++ b/ui/src/routes/devices.$id.settings.general._index.tsx @@ -1,14 +1,17 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, useMemo } from "react"; import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc"; import { useDeviceUiNavigation } from "@hooks/useAppNavigation"; import { useDeviceStore } from "@hooks/stores"; import { Button } from "@components/Button"; import Checkbox from "@components/Checkbox"; +import { SelectMenuBasic } from "@components/SelectMenuBasic"; import { SettingsItem } from "@components/SettingsItem"; import { SettingsPageHeader } from "@components/SettingsPageheader"; import notifications from "@/notifications"; +import { getLocale, setLocale, locales, baseLocale } from '@localizations/runtime.js'; import { m } from "@localizations/messages.js"; +import { deleteCookie, map_locale_code_to_name } from "@/utils"; export default function SettingsGeneralRoute() { const { send } = useJsonRpc(); @@ -40,6 +43,37 @@ export default function SettingsGeneralRoute() { }); }; + const [currentLocale, setCurrentLocale] = useState(getLocale()); + + const localeOptions = useMemo(() => { + return ["", ...locales] + .map((code) => { + const [localizedName, nativeName] = map_locale_code_to_name(code); + // don't repeat the name if it's the same in both locales (or blank) + const label = nativeName && nativeName !== localizedName ? `${localizedName} - ${nativeName}` : localizedName; + return { value: code, label: label } + }); + }, []); + + const handleLocaleChange = (newLocale: string) => { + if (newLocale === currentLocale) return; + + let validLocale = newLocale as typeof locales[number]; + + if (newLocale !== "") { + if (!locales.includes(validLocale)) { + validLocale = baseLocale; + } + + setLocale(validLocale); // tell the i18n system to change locale + } else { + deleteCookie("JETKVM_LOCALE", "", "/"); // delete the cookie that the i18n system uses to store the locale + } + + setCurrentLocale(validLocale); + notifications.success(m.locale_change_success({ locale: validLocale || m.locale_auto() })); + }; + return (