mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
fix: error layout
This commit is contained in:
parent
3de5a8193b
commit
b02e995a99
@ -6,6 +6,7 @@ import Image from "next/image";
|
|||||||
import { Separator } from "../../../components/ui/separator";
|
import { Separator } from "../../../components/ui/separator";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { ModeToggle } from "../../../components/ThemeSwitcher";
|
import { ModeToggle } from "../../../components/ThemeSwitcher";
|
||||||
|
import { LanguageSwitcher } from "@/components/LanguageSwitcher";
|
||||||
function Header() {
|
function Header() {
|
||||||
const t = useTranslations("Header");
|
const t = useTranslations("Header");
|
||||||
return (
|
return (
|
||||||
@ -31,7 +32,10 @@ function Header() {
|
|||||||
{t("p_1079-1199_Simpleandbeautifuldashbo")}
|
{t("p_1079-1199_Simpleandbeautifuldashbo")}
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
<ModeToggle />
|
<section className="flex items-center gap-2">
|
||||||
|
<LanguageSwitcher />
|
||||||
|
<ModeToggle />
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<Overview />
|
<Overview />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,37 @@
|
|||||||
import { useTranslations } from "next-intl";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Header from "@/app/[locale]/(main)/header";
|
import Header from "@/app/[locale]/(main)/header";
|
||||||
import Footer from "./footer";
|
import Footer from "./footer";
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import { Inter as FontSans } from "next/font/google";
|
||||||
|
import { ThemeProvider } from "next-themes";
|
||||||
|
import { Viewport } from "next";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { PublicEnvScript } from "next-runtime-env";
|
||||||
|
|
||||||
|
const fontSans = FontSans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-sans",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
manifest: "/manifest.json",
|
||||||
|
title: "NezhaDash",
|
||||||
|
description: "A dashboard for nezha",
|
||||||
|
appleWebApp: {
|
||||||
|
capable: true,
|
||||||
|
title: "NezhaDash",
|
||||||
|
statusBarStyle: "black-translucent",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const viewport: Viewport = {
|
||||||
|
width: "device-width",
|
||||||
|
initialScale: 1,
|
||||||
|
maximumScale: 1,
|
||||||
|
userScalable: false,
|
||||||
|
};
|
||||||
|
|
||||||
type DashboardProps = {
|
type DashboardProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,37 @@
|
|||||||
// @auto-i18n-check. Please do not delete the line.
|
// @auto-i18n-check. Please do not delete the line.
|
||||||
|
|
||||||
|
import "@/styles/globals.css";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { NextIntlClientProvider, useMessages } from "next-intl";
|
import { NextIntlClientProvider, useMessages } from "next-intl";
|
||||||
|
import { PublicEnvScript } from "next-runtime-env";
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import { Inter as FontSans } from "next/font/google";
|
||||||
|
import { ThemeProvider } from "next-themes";
|
||||||
|
import { Viewport } from "next";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const fontSans = FontSans({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: "--font-sans",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
manifest: "/manifest.json",
|
||||||
|
title: "NezhaDash",
|
||||||
|
description: "A dashboard for nezha",
|
||||||
|
appleWebApp: {
|
||||||
|
capable: true,
|
||||||
|
title: "NezhaDash",
|
||||||
|
statusBarStyle: "black-translucent",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const viewport: Viewport = {
|
||||||
|
width: "device-width",
|
||||||
|
initialScale: 1,
|
||||||
|
maximumScale: 1,
|
||||||
|
userScalable: false,
|
||||||
|
};
|
||||||
|
|
||||||
export default function LocaleLayout({
|
export default function LocaleLayout({
|
||||||
children,
|
children,
|
||||||
@ -12,11 +42,26 @@ export default function LocaleLayout({
|
|||||||
}) {
|
}) {
|
||||||
const messages = useMessages();
|
const messages = useMessages();
|
||||||
return (
|
return (
|
||||||
<html lang={locale}>
|
<html lang={locale} suppressHydrationWarning>
|
||||||
<body>
|
<head>
|
||||||
<NextIntlClientProvider locale={locale} messages={messages}>
|
<PublicEnvScript />
|
||||||
{children}
|
</head>
|
||||||
</NextIntlClientProvider>
|
<body
|
||||||
|
className={cn(
|
||||||
|
"min-h-screen bg-background font-sans antialiased",
|
||||||
|
fontSans.variable,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ThemeProvider
|
||||||
|
attribute="class"
|
||||||
|
defaultTheme="system"
|
||||||
|
enableSystem
|
||||||
|
disableTransitionOnChange
|
||||||
|
>
|
||||||
|
<NextIntlClientProvider locale={locale} messages={messages}>
|
||||||
|
{children}
|
||||||
|
</NextIntlClientProvider>
|
||||||
|
</ThemeProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
import "@/styles/globals.css";
|
|
||||||
|
|
||||||
import type { Metadata } from "next";
|
|
||||||
import { Inter as FontSans } from "next/font/google";
|
|
||||||
import { ThemeProvider } from "next-themes";
|
|
||||||
import React from "react";
|
|
||||||
import { Viewport } from "next";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { PublicEnvScript } from "next-runtime-env";
|
|
||||||
|
|
||||||
const fontSans = FontSans({
|
|
||||||
subsets: ["latin"],
|
|
||||||
variable: "--font-sans",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
manifest: "/manifest.json",
|
|
||||||
title: "NezhaDash",
|
|
||||||
description: "A dashboard for nezha",
|
|
||||||
appleWebApp: {
|
|
||||||
capable: true,
|
|
||||||
title: "NezhaDash",
|
|
||||||
statusBarStyle: "black-translucent",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const viewport: Viewport = {
|
|
||||||
width: "device-width",
|
|
||||||
initialScale: 1,
|
|
||||||
maximumScale: 1,
|
|
||||||
userScalable: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
interface RootLayoutProps {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function RootLayout({ children }: RootLayoutProps) {
|
|
||||||
return (
|
|
||||||
<html lang="en" suppressHydrationWarning>
|
|
||||||
<head>
|
|
||||||
<PublicEnvScript />
|
|
||||||
</head>
|
|
||||||
<body
|
|
||||||
className={cn(
|
|
||||||
"min-h-screen bg-background font-sans antialiased",
|
|
||||||
fontSans.variable,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ThemeProvider
|
|
||||||
attribute="class"
|
|
||||||
defaultTheme="system"
|
|
||||||
enableSystem
|
|
||||||
disableTransitionOnChange
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</ThemeProvider>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
}
|
|
71
components/LanguageSwitcher.tsx
Normal file
71
components/LanguageSwitcher.tsx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useLocale } from "next-intl";
|
||||||
|
import { localeItems } from "../i18n-metadata";
|
||||||
|
import { useRouter, usePathname } from "next/navigation";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
|
||||||
|
export function LanguageSwitcher() {
|
||||||
|
const locale = useLocale();
|
||||||
|
const router = useRouter();
|
||||||
|
const pathname = usePathname();
|
||||||
|
|
||||||
|
const handleChange = (code: string) => {
|
||||||
|
const newLocale = code;
|
||||||
|
|
||||||
|
const rootPath = "/";
|
||||||
|
const currentLocalePath = `/${locale}`;
|
||||||
|
const newLocalePath = `/${newLocale}`;
|
||||||
|
|
||||||
|
// Function to construct new path with locale prefix
|
||||||
|
const constructLocalePath = (path: string, newLocale: string) => {
|
||||||
|
if (path.startsWith(currentLocalePath)) {
|
||||||
|
return path.replace(currentLocalePath, `/${newLocale}`);
|
||||||
|
} else {
|
||||||
|
return `/${newLocale}${path}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pathname === rootPath || !pathname) {
|
||||||
|
router.push(newLocalePath);
|
||||||
|
} else if (
|
||||||
|
pathname === currentLocalePath ||
|
||||||
|
pathname === `${currentLocalePath}/`
|
||||||
|
) {
|
||||||
|
router.push(newLocalePath);
|
||||||
|
} else {
|
||||||
|
const newPath = constructLocalePath(pathname, newLocale);
|
||||||
|
router.push(newPath);
|
||||||
|
}
|
||||||
|
router.refresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="outline" size="sm" className="rounded-full px-[9px]">
|
||||||
|
{localeItems.find((item) => item.code === locale)?.name}
|
||||||
|
<span className="sr-only">Change language</span>
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
{localeItems.map((item) => (
|
||||||
|
<DropdownMenuItem
|
||||||
|
key={item.code}
|
||||||
|
onClick={() => handleChange(item.code)}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
))}
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user