mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 17:41:56 +08:00
feat: dash command
This commit is contained in:
parent
733767a363
commit
c5f81d70d4
@ -36,7 +36,7 @@
|
|||||||
"country-flag-icons": "^1.5.14",
|
"country-flag-icons": "^1.5.14",
|
||||||
"d3-geo": "^3.1.1",
|
"d3-geo": "^3.1.1",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"framer-motion": "^12.0.1",
|
"framer-motion": "^12.0.3",
|
||||||
"i18n-iso-countries": "^7.13.0",
|
"i18n-iso-countries": "^7.13.0",
|
||||||
"i18next": "^24.2.1",
|
"i18next": "^24.2.1",
|
||||||
"lucide-react": "^0.460.0",
|
"lucide-react": "^0.460.0",
|
||||||
@ -53,8 +53,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.18.0",
|
"@eslint/js": "^9.18.0",
|
||||||
"@types/node": "^22.10.8",
|
"@types/node": "^22.10.9",
|
||||||
"@types/react": "^19.0.7",
|
"@types/react": "^19.0.8",
|
||||||
"@types/react-dom": "^19.0.3",
|
"@types/react-dom": "^19.0.3",
|
||||||
"@vitejs/plugin-react-swc": "^3.7.2",
|
"@vitejs/plugin-react-swc": "^3.7.2",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
|
@ -15,6 +15,7 @@ import ErrorPage from "./pages/ErrorPage"
|
|||||||
import NotFound from "./pages/NotFound"
|
import NotFound from "./pages/NotFound"
|
||||||
import Server from "./pages/Server"
|
import Server from "./pages/Server"
|
||||||
import ServerDetail from "./pages/ServerDetail"
|
import ServerDetail from "./pages/ServerDetail"
|
||||||
|
import { DashCommand } from "./components/DashCommand"
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const { data: settingData, error } = useQuery({
|
const { data: settingData, error } = useQuery({
|
||||||
@ -90,6 +91,7 @@ const App: React.FC = () => {
|
|||||||
<main className="flex z-20 min-h-[calc(100vh-calc(var(--spacing)*16))] flex-1 flex-col gap-4 p-4 md:p-10 md:pt-8">
|
<main className="flex z-20 min-h-[calc(100vh-calc(var(--spacing)*16))] flex-1 flex-col gap-4 p-4 md:p-10 md:pt-8">
|
||||||
<RefreshToast />
|
<RefreshToast />
|
||||||
<Header />
|
<Header />
|
||||||
|
<DashCommand />
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Server />} />
|
<Route path="/" element={<Server />} />
|
||||||
<Route path="/server/:id" element={<ServerDetail />} />
|
<Route path="/server/:id" element={<ServerDetail />} />
|
||||||
|
114
src/components/DashCommand.tsx
Normal file
114
src/components/DashCommand.tsx
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from "@/components/ui/command"
|
||||||
|
import { useTheme } from "@/hooks/use-theme"
|
||||||
|
import { useWebSocketContext } from "@/hooks/use-websocket-context"
|
||||||
|
import { formatNezhaInfo } from "@/lib/utils"
|
||||||
|
import { NezhaWebsocketResponse } from "@/types/nezha-api"
|
||||||
|
import { Home, Moon, Sun, SunMoon } from "lucide-react"
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { useNavigate } from "react-router-dom"
|
||||||
|
|
||||||
|
export function DashCommand() {
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const [search, setSearch] = useState("")
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { setTheme } = useTheme()
|
||||||
|
|
||||||
|
const { lastMessage, connected } = useWebSocketContext()
|
||||||
|
|
||||||
|
const nezhaWsData = lastMessage ? (JSON.parse(lastMessage.data) as NezhaWebsocketResponse) : null
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const down = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
||||||
|
e.preventDefault()
|
||||||
|
setOpen((open) => !open)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("keydown", down)
|
||||||
|
return () => document.removeEventListener("keydown", down)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (!connected || !nezhaWsData) return null
|
||||||
|
|
||||||
|
const shortcuts = [
|
||||||
|
{
|
||||||
|
keywords: ["home", "homepage"],
|
||||||
|
icon: <Home />,
|
||||||
|
label: t("Home"),
|
||||||
|
action: () => navigate("/"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keywords: ["light", "theme", "lightmode"],
|
||||||
|
icon: <Sun />,
|
||||||
|
label: t("ToggleLightMode"),
|
||||||
|
action: () => setTheme("light"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keywords: ["dark", "theme", "darkmode"],
|
||||||
|
icon: <Moon />,
|
||||||
|
label: t("ToggleDarkMode"),
|
||||||
|
action: () => setTheme("dark"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keywords: ["system", "theme", "systemmode"],
|
||||||
|
icon: <SunMoon />,
|
||||||
|
label: t("ToggleSystemMode"),
|
||||||
|
action: () => setTheme("system"),
|
||||||
|
},
|
||||||
|
].map((item) => ({
|
||||||
|
...item,
|
||||||
|
value: `${item.keywords.join(" ")} ${item.label}`,
|
||||||
|
}))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CommandDialog open={open} onOpenChange={setOpen}>
|
||||||
|
<CommandInput placeholder={t("TypeCommand")} value={search} onValueChange={setSearch} />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>{t("NoResults")}</CommandEmpty>
|
||||||
|
<CommandGroup heading={t("Servers")}>
|
||||||
|
{nezhaWsData.servers.map((server) => (
|
||||||
|
<CommandItem
|
||||||
|
key={server.id}
|
||||||
|
value={server.name}
|
||||||
|
onSelect={() => {
|
||||||
|
navigate(`/server/${server.id}`)
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatNezhaInfo(nezhaWsData.now, server).online ? (
|
||||||
|
<span className="h-2 w-2 shrink-0 rounded-full bg-green-500 self-center" />
|
||||||
|
) : (
|
||||||
|
<span className="h-2 w-2 shrink-0 rounded-full bg-red-500 self-center" />
|
||||||
|
)}
|
||||||
|
<span>{server.name}</span>
|
||||||
|
</CommandItem>
|
||||||
|
))}
|
||||||
|
</CommandGroup>
|
||||||
|
<CommandSeparator />
|
||||||
|
|
||||||
|
<CommandGroup heading={t("Shortcuts")}>
|
||||||
|
{shortcuts.map((item) => (
|
||||||
|
<CommandItem
|
||||||
|
key={item.label}
|
||||||
|
value={item.value}
|
||||||
|
onSelect={() => {
|
||||||
|
item.action()
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.icon}
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</CommandItem>
|
||||||
|
))}
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</CommandDialog>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -24,7 +24,13 @@ const Footer: React.FC = () => {
|
|||||||
</a>
|
</a>
|
||||||
<p>{settingData?.data?.version || ""}</p>
|
<p>{settingData?.data?.version || ""}</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="server-footer-theme">
|
<div className="server-footer-theme flex flex-col items-center sm:items-end">
|
||||||
|
<p className="mt-1 text-[13px] font-light tracking-tight text-neutral-600/50 dark:text-neutral-300/50">
|
||||||
|
<kbd className="pointer-events-none mx-1 inline-flex h-4 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">
|
||||||
|
<span className="text-xs">⌘</span>K
|
||||||
|
</kbd>
|
||||||
|
</p>
|
||||||
|
<section>
|
||||||
{t("footer.themeBy")}
|
{t("footer.themeBy")}
|
||||||
<a href={"https://github.com/hamster1963/nezha-dash"} target="_blank">
|
<a href={"https://github.com/hamster1963/nezha-dash"} target="_blank">
|
||||||
nezha-dash
|
nezha-dash
|
||||||
@ -34,7 +40,8 @@ const Footer: React.FC = () => {
|
|||||||
({import.meta.env.VITE_GIT_HASH})
|
({import.meta.env.VITE_GIT_HASH})
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</p>
|
</section>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -1,31 +1,29 @@
|
|||||||
import * as React from "react"
|
"use client"
|
||||||
import { type DialogProps } from "@radix-ui/react-dialog"
|
|
||||||
|
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { type DialogProps, DialogTitle } from "@radix-ui/react-dialog"
|
||||||
import { Command as CommandPrimitive } from "cmdk"
|
import { Command as CommandPrimitive } from "cmdk"
|
||||||
import { Search } from "lucide-react"
|
import { Search } from "lucide-react"
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
const Command = React.forwardRef<React.ElementRef<typeof CommandPrimitive>, React.ComponentPropsWithoutRef<typeof CommandPrimitive>>(
|
||||||
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
({ className, ...props }, ref) => (
|
||||||
|
|
||||||
const Command = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CommandPrimitive>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CommandPrimitive
|
<CommandPrimitive
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn("flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", className)}
|
||||||
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
),
|
||||||
|
)
|
||||||
Command.displayName = CommandPrimitive.displayName
|
Command.displayName = CommandPrimitive.displayName
|
||||||
|
|
||||||
const CommandDialog = ({ children, ...props }: DialogProps) => {
|
const CommandDialog = ({ children, ...props }: DialogProps) => {
|
||||||
return (
|
return (
|
||||||
<Dialog {...props}>
|
<Dialog {...props}>
|
||||||
|
<DialogTitle />
|
||||||
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
||||||
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-4 [&_[cmdk-input-wrapper]_svg]:w-4 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-4 [&_[cmdk-item]_svg]:w-4">
|
||||||
{children}
|
{children}
|
||||||
</Command>
|
</Command>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
@ -33,119 +31,77 @@ const CommandDialog = ({ children, ...props }: DialogProps) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommandInput = React.forwardRef<
|
const CommandInput = React.forwardRef<React.ElementRef<typeof CommandPrimitive.Input>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>>(
|
||||||
React.ElementRef<typeof CommandPrimitive.Input>,
|
({ className, ...props }, ref) => (
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
<div className="flex items-center border-b bg-stone-100 dark:bg-stone-900 px-3" cmdk-input-wrapper="">
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
|
||||||
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
<CommandPrimitive.Input
|
<CommandPrimitive.Input
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
CommandInput.displayName = CommandPrimitive.Input.displayName
|
CommandInput.displayName = CommandPrimitive.Input.displayName
|
||||||
|
|
||||||
const CommandList = React.forwardRef<
|
const CommandList = React.forwardRef<React.ElementRef<typeof CommandPrimitive.List>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>>(
|
||||||
React.ElementRef<typeof CommandPrimitive.List>,
|
({ className, ...props }, ref) => (
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
<CommandPrimitive.List ref={ref} className={cn("max-h-[300px] mb-1 overflow-y-auto overflow-x-hidden", className)} {...props} />
|
||||||
>(({ className, ...props }, ref) => (
|
),
|
||||||
<CommandPrimitive.List
|
)
|
||||||
ref={ref}
|
|
||||||
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
|
|
||||||
CommandList.displayName = CommandPrimitive.List.displayName
|
CommandList.displayName = CommandPrimitive.List.displayName
|
||||||
|
|
||||||
const CommandEmpty = React.forwardRef<
|
const CommandEmpty = React.forwardRef<React.ElementRef<typeof CommandPrimitive.Empty>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>>(
|
||||||
React.ElementRef<typeof CommandPrimitive.Empty>,
|
(props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />,
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
)
|
||||||
>((props, ref) => (
|
|
||||||
<CommandPrimitive.Empty
|
|
||||||
ref={ref}
|
|
||||||
className="py-6 text-center text-sm"
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
|
|
||||||
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
|
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
|
||||||
|
|
||||||
const CommandGroup = React.forwardRef<
|
const CommandGroup = React.forwardRef<React.ElementRef<typeof CommandPrimitive.Group>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>>(
|
||||||
React.ElementRef<typeof CommandPrimitive.Group>,
|
({ className, ...props }, ref) => (
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CommandPrimitive.Group
|
<CommandPrimitive.Group
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
CommandGroup.displayName = CommandPrimitive.Group.displayName
|
CommandGroup.displayName = CommandPrimitive.Group.displayName
|
||||||
|
|
||||||
const CommandSeparator = React.forwardRef<
|
const CommandSeparator = React.forwardRef<
|
||||||
React.ElementRef<typeof CommandPrimitive.Separator>,
|
React.ElementRef<typeof CommandPrimitive.Separator>,
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => <CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} />)
|
||||||
<CommandPrimitive.Separator
|
|
||||||
ref={ref}
|
|
||||||
className={cn("-mx-1 h-px bg-border", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
|
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
|
||||||
|
|
||||||
const CommandItem = React.forwardRef<
|
const CommandItem = React.forwardRef<React.ElementRef<typeof CommandPrimitive.Item>, React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>>(
|
||||||
React.ElementRef<typeof CommandPrimitive.Item>,
|
({ className, ...props }, ref) => (
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CommandPrimitive.Item
|
<CommandPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
"relative flex cursor-default gap-2 select-none items-center rounded-[8px] px-2 py-1.5 text-xs outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-stone-100 dark:data-[selected='true']:bg-stone-900 data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
CommandItem.displayName = CommandPrimitive.Item.displayName
|
CommandItem.displayName = CommandPrimitive.Item.displayName
|
||||||
|
|
||||||
const CommandShortcut = ({
|
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||||
className,
|
return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />
|
||||||
...props
|
|
||||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className={cn(
|
|
||||||
"ml-auto text-xs tracking-widest text-muted-foreground",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
CommandShortcut.displayName = "CommandShortcut"
|
CommandShortcut.displayName = "CommandShortcut"
|
||||||
|
|
||||||
export {
|
export { Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandShortcut, CommandSeparator }
|
||||||
Command,
|
|
||||||
CommandDialog,
|
|
||||||
CommandInput,
|
|
||||||
CommandList,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandItem,
|
|
||||||
CommandShortcut,
|
|
||||||
CommandSeparator,
|
|
||||||
}
|
|
||||||
|
@ -116,5 +116,13 @@
|
|||||||
"price": "Price",
|
"price": "Price",
|
||||||
"free": "Free",
|
"free": "Free",
|
||||||
"usage-baseed": "Usage-based"
|
"usage-baseed": "Usage-based"
|
||||||
}
|
},
|
||||||
|
"TypeCommand": "Type a command or search...",
|
||||||
|
"NoResults": "No results found.",
|
||||||
|
"Servers": "Servers",
|
||||||
|
"Shortcuts": "Shortcuts",
|
||||||
|
"ToggleLightMode": "Toggle Light Mode",
|
||||||
|
"ToggleDarkMode": "Toggle Dark Mode",
|
||||||
|
"ToggleSystemMode": "Toggle System Mode",
|
||||||
|
"Home": "Home"
|
||||||
}
|
}
|
||||||
|
@ -116,5 +116,13 @@
|
|||||||
"price": "价格",
|
"price": "价格",
|
||||||
"free": "免费",
|
"free": "免费",
|
||||||
"usage-baseed": "按量计费"
|
"usage-baseed": "按量计费"
|
||||||
}
|
},
|
||||||
|
"TypeCommand": "输入命令或搜索",
|
||||||
|
"NoResults": "结果为空",
|
||||||
|
"Servers": "服务器",
|
||||||
|
"Shortcuts": "快捷键",
|
||||||
|
"ToggleLightMode": "切换亮色模式",
|
||||||
|
"ToggleDarkMode": "切换暗色模式",
|
||||||
|
"ToggleSystemMode": "切换系统模式",
|
||||||
|
"Home": "首页"
|
||||||
}
|
}
|
||||||
|
@ -112,5 +112,13 @@
|
|||||||
"price": "價格",
|
"price": "價格",
|
||||||
"free": "免費",
|
"free": "免費",
|
||||||
"usage-baseed": "按量計費"
|
"usage-baseed": "按量計費"
|
||||||
}
|
},
|
||||||
|
"TypeCommand": "輸入命令或搜尋",
|
||||||
|
"NoResults": "沒有結果",
|
||||||
|
"Servers": "伺服器",
|
||||||
|
"Shortcuts": "快捷鍵",
|
||||||
|
"ToggleLightMode": "切換亮色模式",
|
||||||
|
"ToggleDarkMode": "切換暗色模式",
|
||||||
|
"ToggleSystemMode": "切換系統模式",
|
||||||
|
"Home": "首頁"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user