add i18n support

This commit is contained in:
oupula 2025-09-30 12:40:33 +08:00
parent 789dcb3797
commit 353b58a835
13 changed files with 58 additions and 63 deletions

View File

@ -1 +0,0 @@
{}

View File

@ -1 +0,0 @@
{}

View File

@ -18,7 +18,7 @@ import { cx } from "@/cva.config";
import PasteModal from "@/components/popovers/PasteModal";
import WakeOnLanModal from "@/components/popovers/WakeOnLan/Index";
import MountPopopover from "@/components/popovers/MountPopover";
import {ExtensionPopover} from "@/components/popovers/ExtensionPopover";
import { ExtensionPopover } from "@/components/popovers/ExtensionPopover";
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
export default function Actionbar({

View File

@ -1,5 +1,4 @@
import { useTranslation } from "react-i18next";
import {
CheckCircleIcon,
ExclamationTriangleIcon,
@ -58,15 +57,15 @@ const variantConfig = {
buttonTheme: "danger" | "primary" | "blank" | "light" | "lightDanger";
}
>;
// @ts-ignore
export function ConfirmDialog({
open,
onClose,
title,
description,
variant = "info",
confirmText = useTranslation('Confirm').toString(),
cancelText = useTranslation('Cancel').toString(),
confirmText = 'Confirm',
cancelText = 'Cancel',
onConfirm,
isConfirming = false,
}: ConfirmDialogProps) {

View File

@ -96,19 +96,19 @@ export default function InfoBar() {
{debugMode && (
<div className="flex w-[156px] items-center gap-x-1">
<span className="text-xs font-semibold">{t('USB_State')}:</span>
<span className="text-xs">{t(usbState.replace(' ','_').toString())}</span>
<span className="text-xs">{t(usbState)}</span>
</div>
)}
{debugMode && (
<div className="flex w-[156px] items-center gap-x-1">
<span className="text-xs font-semibold">{t('HDMI_State')}:</span>
<span className="text-xs">{t(hdmiState.toString())}</span>
<span className="text-xs">{t(hdmiState)}</span>
</div>
)}
{debugMode && (
<div className="flex w-[168px] items-center gap-x-1">
<span className="text-xs font-semibold">{t('HidRPC_State')}:</span>
<span className="text-xs">{t(rpcHidStatus.toString().replace(' ','_'))}</span>
<span className="text-xs">{t(rpcHidStatus)}</span>
</div>
)}
{isPasteInProgress && (

View File

@ -1,13 +1,15 @@
import StatusCard from "@components/StatusCards";
import {useTranslation} from "react-i18next";
import StatusCard from "@components/StatusCards";
const PeerConnectionStatusMap = {
connected: "Connected",
connecting: "Connecting",
disconnected: "Disconnected",
error: "Connection error",
error: "Connection_error",
closing: "Closing",
failed: "Connection failed",
failed: "Connection_failed",
closed: "Closed",
new: "Connecting",
} as Record<RTCPeerConnectionState | "error" | "closing", string>;
@ -28,7 +30,8 @@ export default function PeerConnectionStatusCard({
state?: RTCPeerConnectionState | null;
title?: string;
}) {
if (!state) return <></>;
if (!state) return;
// eslint-disable-next-line react-hooks/rules-of-hooks
const { t } = useTranslation();
const StatusCardProps: StatusProps = {
connected: {
@ -57,7 +60,7 @@ export default function PeerConnectionStatusCard({
},
};
const props = StatusCardProps[state];
if (!props) return (<div></div>);
if (!props) return;
return (
<StatusCard
title={title || "JetKVM Device"}

View File

@ -33,7 +33,7 @@ const StatusCardProps: StatusProps = {
iconClassName: "h-5 w-5 text-blue-500",
statusIndicatorClassName: "bg-slate-300 border-slate-400",
},
"not attached": {
"not_attached": {
icon: ({ className }) => (
<img className={cx(className)} src={KeyboardAndMouseConnectedIcon} alt="" />
),
@ -61,7 +61,7 @@ export default function USBStateStatus({
configured: t('Connected'),
attached: t('Connecting'),
addressed: t('Connecting'),
"not attached": t('Disconnected'),
"not_attached": t('Disconnected'),
suspended: t('Low_power_mode'),
};
const props = StatusCardProps[state];
@ -76,7 +76,7 @@ export default function USBStateStatus({
icon: Icon,
iconClassName,
statusIndicatorClassName,
} = StatusCardProps["not attached"];
} = StatusCardProps["not_attached"];
return (
<StatusCard

View File

@ -171,7 +171,7 @@ export function UsbInfoSetting() {
handleUsbConfigChange(usbConfig);
}
}}
options={[...usbConfigs, { value: "custom", label: "Custom" }]}
options={[...usbConfigs, { value: "custom", label: t('Custom') }]}
/>
</SettingsItem>
{usbConfigProduct === "custom" && (

View File

@ -468,7 +468,7 @@ export interface KeysDownState {
export type USBStates =
| "configured"
| "attached"
| "not attached"
| "not_attached"
| "suspended"
| "addressed";
@ -503,7 +503,7 @@ export const useHidStore = create<HidState>(set => ({
setPasteModeEnabled: (enabled: boolean): void => set({ isPasteInProgress: enabled }),
// Add these new properties for USB state
usbState: "not attached",
usbState: "not_attached",
setUsbState: (state: USBStates) => set({ usbState: state }),
}));

View File

@ -52,7 +52,7 @@ function ConfirmationBox({
<div className="flex flex-col items-start justify-start space-y-4 text-left">
<div className="text-left">
<p className="text-base font-semibold text-black dark:text-white">
{t('重启JetKVM')}
{t('Reboot_JetKVM')}
</p>
<p className="text-sm text-slate-600 dark:text-slate-300">
{t('Do_you_want_to_proceed_with_rebooting_the_system')}

View File

@ -12,12 +12,20 @@ import notifications from "@/notifications";
import { SettingsItem } from "./devices.$id.settings";
const defaultEdid =
export default function SettingsVideoRoute() {
const { send } = useJsonRpc();
const { t } = useTranslation();
const [streamQuality, setStreamQuality] = useState("1");
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
const [edid, setEdid] = useState<string | null>(null);
const [edidLoading, setEdidLoading] = useState(false);
const defaultEdid =
"00ffffffffffff0052620188008888881c150103800000780a0dc9a05747982712484c00000001010101010101010101010101010101023a801871382d40582c4500c48e2100001e011d007251d01e206e285500c48e2100001e000000fc00543734392d6648443732300a20000000fd00147801ff1d000a202020202020017b";
const edids = [
const edids = [
{
value: defaultEdid,
label: "JetKVM Default",
label: t('JetKVM_Default'),
},
{
value:
@ -39,22 +47,13 @@ const edids = [
"00ffffffffffff0010ac0100020000000111010380221bff0a00000000000000000000adce0781800101010101010101010101010101000000ff0030303030303030303030303030000000ff0030303030303030303030303030000000fd00384c1f530b000a000000000000000000fc0044454c4c2049445241430a2020000a",
label: "DELL IDRAC EDID, 1280x1024",
},
];
const streamQualityOptions = [
{ value: "1", label: "High" },
{ value: "0.5", label: "Medium" },
{ value: "0.1", label: "Low" },
];
export default function SettingsVideoRoute() {
const { send } = useJsonRpc();
const { t } = useTranslation();
const [streamQuality, setStreamQuality] = useState("1");
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
const [edid, setEdid] = useState<string | null>(null);
const [edidLoading, setEdidLoading] = useState(false);
];
const streamQualityOptions = [
{ value: "1", label: t("High") },
{ value: "0.5", label: t('Medium') },
{ value: "0.1", label: t('Low') },
];
// Video enhancement settings from store
const {
videoSaturation,

View File

@ -366,11 +366,7 @@ export default function KvmIdRoute() {
const sessionUrl = `${CLOUD_API}/webrtc/session`;
console.log("Trying to get remote session description");
setLoadingMessage(
t('Getting_remote_session_description',{
attempt:signalingAttempts.current > 0 ? t('attempt_num',{num:signalingAttempts.current + 1}) : ''
})
);//Getting remote session description... ${signalingAttempts.current > 0 ? `(attempt ${signalingAttempts.current + 1})` : ""}`,
setLoadingMessage(t('Getting_remote_session_description',{ attempt: signalingAttempts.current > 0 ? t('attempt_num', { num:signalingAttempts.current + 1 }) : '' }));
const res = await api.POST(sessionUrl, {
sd,
// When on device, we don't need to specify the device id, as it's already known