mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat(i18n): add i18n support for sidebar
This commit is contained in:
@@ -86,6 +86,7 @@ import { Logo } from "../shared/logo";
|
||||
import { Button } from "../ui/button";
|
||||
import { UpdateServerButton } from "./update-server";
|
||||
import { UserNav } from "./user-nav";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
// The types of the queries we are going to use
|
||||
type AuthQueryOutput = inferRouterOutputs<AppRouter>["user"]["get"];
|
||||
@@ -93,6 +94,7 @@ type AuthQueryOutput = inferRouterOutputs<AppRouter>["user"]["get"];
|
||||
type SingleNavItem = {
|
||||
isSingle?: true;
|
||||
title: string;
|
||||
titleKey: string;
|
||||
url: string;
|
||||
icon?: LucideIcon;
|
||||
isEnabled?: (opts: {
|
||||
@@ -110,6 +112,7 @@ type NavItem =
|
||||
| {
|
||||
isSingle: false;
|
||||
title: string;
|
||||
titleKey: string;
|
||||
icon: LucideIcon;
|
||||
items: SingleNavItem[];
|
||||
isEnabled?: (opts: {
|
||||
@@ -122,6 +125,7 @@ type NavItem =
|
||||
// Represents an external link item (used for the help section)
|
||||
type ExternalLink = {
|
||||
name: string;
|
||||
nameKey: string;
|
||||
url: string;
|
||||
icon: React.ComponentType<{ className?: string }>;
|
||||
isEnabled?: (opts: {
|
||||
@@ -147,12 +151,14 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Projects",
|
||||
titleKey: "common.side.projects",
|
||||
url: "/dashboard/projects",
|
||||
icon: Folder,
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Monitoring",
|
||||
titleKey: "common.side.monitoring",
|
||||
url: "/dashboard/monitoring",
|
||||
icon: BarChartHorizontalBigIcon,
|
||||
// Only enabled in non-cloud environments
|
||||
@@ -161,6 +167,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Traefik File System",
|
||||
titleKey: "common.side.traefik",
|
||||
url: "/dashboard/traefik",
|
||||
icon: GalleryVerticalEnd,
|
||||
// Only enabled for admins and users with access to Traefik files in non-cloud environments
|
||||
@@ -173,6 +180,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Docker",
|
||||
titleKey: "common.side.docker",
|
||||
url: "/dashboard/docker",
|
||||
icon: BlocksIcon,
|
||||
// Only enabled for admins and users with access to Docker in non-cloud environments
|
||||
@@ -182,6 +190,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Swarm",
|
||||
titleKey: "common.side.swarm",
|
||||
url: "/dashboard/swarm",
|
||||
icon: PieChart,
|
||||
// Only enabled for admins and users with access to Docker in non-cloud environments
|
||||
@@ -191,6 +200,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Requests",
|
||||
titleKey: "common.side.requests",
|
||||
url: "/dashboard/requests",
|
||||
icon: Forward,
|
||||
// Only enabled for admins and users with access to Docker in non-cloud environments
|
||||
@@ -259,6 +269,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Web Server",
|
||||
titleKey: "common.side.web-server",
|
||||
url: "/dashboard/settings/server",
|
||||
icon: Activity,
|
||||
// Only enabled for admins in non-cloud environments
|
||||
@@ -267,12 +278,14 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Profile",
|
||||
titleKey: "common.side.profile",
|
||||
url: "/dashboard/settings/profile",
|
||||
icon: User,
|
||||
},
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Remote Servers",
|
||||
titleKey: "common.side.remote-servers",
|
||||
url: "/dashboard/settings/servers",
|
||||
icon: Server,
|
||||
// Only enabled for admins
|
||||
@@ -281,6 +294,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Users",
|
||||
titleKey: "common.side.users",
|
||||
icon: Users,
|
||||
url: "/dashboard/settings/users",
|
||||
// Only enabled for admins
|
||||
@@ -289,6 +303,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "SSH Keys",
|
||||
titleKey: "common.side.ssh-keys",
|
||||
icon: KeyRound,
|
||||
url: "/dashboard/settings/ssh-keys",
|
||||
// Only enabled for admins and users with access to SSH keys
|
||||
@@ -297,6 +312,7 @@ const MENU: Menu = {
|
||||
},
|
||||
{
|
||||
title: "AI",
|
||||
titleKey: "common.side.ai",
|
||||
icon: BotIcon,
|
||||
url: "/dashboard/settings/ai",
|
||||
isSingle: true,
|
||||
@@ -305,6 +321,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Git",
|
||||
titleKey: "common.side.git",
|
||||
url: "/dashboard/settings/git-providers",
|
||||
icon: GitBranch,
|
||||
// Only enabled for admins and users with access to Git providers
|
||||
@@ -314,6 +331,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Registry",
|
||||
titleKey: "common.side.registry",
|
||||
url: "/dashboard/settings/registry",
|
||||
icon: Package,
|
||||
// Only enabled for admins
|
||||
@@ -322,6 +340,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "S3 Destinations",
|
||||
titleKey: "common.side.s3-destinations",
|
||||
url: "/dashboard/settings/destinations",
|
||||
icon: Database,
|
||||
// Only enabled for admins
|
||||
@@ -331,6 +350,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Certificates",
|
||||
titleKey: "common.side.certificates",
|
||||
url: "/dashboard/settings/certificates",
|
||||
icon: ShieldCheck,
|
||||
// Only enabled for admins
|
||||
@@ -339,6 +359,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Cluster",
|
||||
titleKey: "common.side.cluster",
|
||||
url: "/dashboard/settings/cluster",
|
||||
icon: Boxes,
|
||||
// Only enabled for admins in non-cloud environments
|
||||
@@ -347,6 +368,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Notifications",
|
||||
titleKey: "common.side.notifications",
|
||||
url: "/dashboard/settings/notifications",
|
||||
icon: Bell,
|
||||
// Only enabled for admins
|
||||
@@ -355,6 +377,7 @@ const MENU: Menu = {
|
||||
{
|
||||
isSingle: true,
|
||||
title: "Billing",
|
||||
titleKey: "common.side.billing",
|
||||
url: "/dashboard/settings/billing",
|
||||
icon: CreditCard,
|
||||
// Only enabled for admins in cloud environments
|
||||
@@ -365,16 +388,19 @@ const MENU: Menu = {
|
||||
help: [
|
||||
{
|
||||
name: "Documentation",
|
||||
nameKey: "common.side.documentation",
|
||||
url: "https://docs.dokploy.com/docs/core",
|
||||
icon: BookIcon,
|
||||
},
|
||||
{
|
||||
name: "Support",
|
||||
nameKey: "common.side.support",
|
||||
url: "https://discord.gg/2tBnJ3jDJc",
|
||||
icon: CircleHelp,
|
||||
},
|
||||
{
|
||||
name: "Sponsor",
|
||||
nameKey: "common.side.sponsor",
|
||||
url: "https://opencollective.com/dokploy",
|
||||
icon: ({ className }) => (
|
||||
<HeartIcon
|
||||
@@ -493,6 +519,7 @@ function LogoWrapper() {
|
||||
}
|
||||
|
||||
function SidebarLogo() {
|
||||
const { t } = useTranslation("common");
|
||||
const { state } = useSidebar();
|
||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||
const { data: user } = api.user.get.useQuery();
|
||||
@@ -689,7 +716,9 @@ function SidebarLogo() {
|
||||
side={"right"}
|
||||
className="w-80"
|
||||
>
|
||||
<DropdownMenuLabel>Pending Invitations</DropdownMenuLabel>
|
||||
<DropdownMenuLabel>
|
||||
{t("common.side.invitations.pending-invitations")}
|
||||
</DropdownMenuLabel>
|
||||
<div className="flex flex-col gap-2">
|
||||
{invitations && invitations.length > 0 ? (
|
||||
invitations.map((invitation) => (
|
||||
@@ -702,16 +731,23 @@ function SidebarLogo() {
|
||||
{invitation?.organization?.name}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Expires:{" "}
|
||||
{new Date(invitation.expiresAt).toLocaleString()}
|
||||
{t("common.side.invitations.expires", {
|
||||
expireDate: new Date(
|
||||
invitation.expiresAt,
|
||||
).toLocaleString(),
|
||||
})}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Role: {invitation.role}
|
||||
{t("common.side.invitations.role", {
|
||||
role: invitation.role,
|
||||
})}
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
<DialogAction
|
||||
title="Accept Invitation"
|
||||
description="Are you sure you want to accept this invitation?"
|
||||
title={t("common.side.invitations.accept-invitation")}
|
||||
description={t(
|
||||
"common.side.invitations.confirm-accept-invitation",
|
||||
)}
|
||||
type="default"
|
||||
onClick={async () => {
|
||||
const { error } =
|
||||
@@ -721,24 +757,31 @@ function SidebarLogo() {
|
||||
|
||||
if (error) {
|
||||
toast.error(
|
||||
error.message || "Error accepting invitation",
|
||||
error.message ||
|
||||
t(
|
||||
"common.side.invitations.error-accepting-invitation",
|
||||
),
|
||||
);
|
||||
} else {
|
||||
toast.success("Invitation accepted successfully");
|
||||
toast.success(
|
||||
t(
|
||||
"common.side.invitations.invitation-accepted",
|
||||
),
|
||||
);
|
||||
await refetchInvitations();
|
||||
await refetch();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Button size="sm" variant="secondary">
|
||||
Accept Invitation
|
||||
{t("common.side.invitations.accept-invitation")}
|
||||
</Button>
|
||||
</DialogAction>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<DropdownMenuItem disabled>
|
||||
No pending invitations
|
||||
{t("common.side.invitations.no-pending-invitations")}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</div>
|
||||
@@ -752,6 +795,8 @@ function SidebarLogo() {
|
||||
}
|
||||
|
||||
export default function Page({ children }: Props) {
|
||||
const { t } = useTranslation("common");
|
||||
|
||||
const [defaultOpen, setDefaultOpen] = useState<boolean | undefined>(
|
||||
undefined,
|
||||
);
|
||||
@@ -818,7 +863,7 @@ export default function Page({ children }: Props) {
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Home</SidebarGroupLabel>
|
||||
<SidebarGroupLabel>{t("common.side.home")}</SidebarGroupLabel>
|
||||
<SidebarMenu>
|
||||
{filteredHome.map((item) => {
|
||||
const isSingle = item.isSingle !== false;
|
||||
@@ -851,7 +896,7 @@ export default function Page({ children }: Props) {
|
||||
className={cn(isActive && "text-primary")}
|
||||
/>
|
||||
)}
|
||||
<span>{item.title}</span>
|
||||
<span>{t(item.titleKey)}</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
) : (
|
||||
@@ -907,7 +952,7 @@ export default function Page({ children }: Props) {
|
||||
</SidebarMenu>
|
||||
</SidebarGroup>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Settings</SidebarGroupLabel>
|
||||
<SidebarGroupLabel>{t("common.side.settings")}</SidebarGroupLabel>
|
||||
<SidebarMenu className="gap-2">
|
||||
{filteredSettings.map((item) => {
|
||||
const isSingle = item.isSingle !== false;
|
||||
@@ -940,7 +985,7 @@ export default function Page({ children }: Props) {
|
||||
className={cn(isActive && "text-primary")}
|
||||
/>
|
||||
)}
|
||||
<span>{item.title}</span>
|
||||
<span>{t(item.titleKey)}</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
) : (
|
||||
@@ -996,7 +1041,7 @@ export default function Page({ children }: Props) {
|
||||
</SidebarMenu>
|
||||
</SidebarGroup>
|
||||
<SidebarGroup className="group-data-[collapsible=icon]:hidden">
|
||||
<SidebarGroupLabel>Extra</SidebarGroupLabel>
|
||||
<SidebarGroupLabel>{t("common.side.extra")}</SidebarGroupLabel>
|
||||
<SidebarMenu>
|
||||
{help.map((item: ExternalLink) => (
|
||||
<SidebarMenuItem key={item.name}>
|
||||
@@ -1010,7 +1055,7 @@ export default function Page({ children }: Props) {
|
||||
<span className="mr-2">
|
||||
<item.icon className="h-4 w-4" />
|
||||
</span>
|
||||
<span>{item.name}</span>
|
||||
<span>{t(item.nameKey)}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
|
||||
@@ -55,7 +55,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["settings"])),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ShowBilling } from "@/components/dashboard/settings/billing/show-billin
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { IS_CLOUD } from "@dokploy/server/constants";
|
||||
import { validateRequest } from "@dokploy/server/lib/auth";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
@@ -30,6 +31,7 @@ export async function getServerSideProps(
|
||||
};
|
||||
}
|
||||
const { req, res } = ctx;
|
||||
const locale = getLocale(req.cookies);
|
||||
const { user, session } = await validateRequest(req);
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
@@ -59,6 +61,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ShowCertificates } from "@/components/dashboard/settings/certificates/s
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { validateRequest } from "@dokploy/server";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
@@ -24,6 +25,7 @@ export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
const { user, session } = await validateRequest(req);
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
@@ -51,6 +53,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ShowNodes } from "@/components/dashboard/settings/cluster/nodes/show-no
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { IS_CLOUD, validateRequest } from "@dokploy/server";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
@@ -25,6 +26,7 @@ export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
if (IS_CLOUD) {
|
||||
return {
|
||||
redirect: {
|
||||
@@ -58,6 +60,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ShowDestinations } from "@/components/dashboard/settings/destination/sh
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { validateRequest } from "@dokploy/server";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
@@ -25,6 +26,7 @@ export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
const { user, session } = await validateRequest(req);
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
@@ -52,6 +54,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ShowGitProviders } from "@/components/dashboard/settings/git/show-git-p
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { validateRequest } from "@dokploy/server";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
@@ -9,68 +10,72 @@ import type { ReactElement } from "react";
|
||||
import superjson from "superjson";
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
<ShowGitProviders />
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
<ShowGitProviders />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
||||
Page.getLayout = (page: ReactElement) => {
|
||||
return <DashboardLayout metaName="Git Providers">{page}</DashboardLayout>;
|
||||
return <DashboardLayout metaName="Git Providers">{page}</DashboardLayout>;
|
||||
};
|
||||
export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>
|
||||
) {
|
||||
const { user, session } = await validateRequest(ctx.req);
|
||||
if (!user) {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
destination: "/",
|
||||
},
|
||||
};
|
||||
}
|
||||
const { req, res } = ctx;
|
||||
const helpers = createServerSideHelpers({
|
||||
router: appRouter,
|
||||
ctx: {
|
||||
req: req as any,
|
||||
res: res as any,
|
||||
db: null as any,
|
||||
session: session as any,
|
||||
user: user as any,
|
||||
},
|
||||
transformer: superjson,
|
||||
});
|
||||
await helpers.user.get.prefetch();
|
||||
try {
|
||||
await helpers.project.all.prefetch();
|
||||
await helpers.settings.isCloud.prefetch();
|
||||
if (user.role === "member") {
|
||||
const userR = await helpers.user.one.fetch({
|
||||
userId: user.id,
|
||||
});
|
||||
const { user, session } = await validateRequest(ctx.req);
|
||||
if (!user) {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
destination: "/",
|
||||
},
|
||||
};
|
||||
}
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
const helpers = createServerSideHelpers({
|
||||
router: appRouter,
|
||||
ctx: {
|
||||
req: req as any,
|
||||
res: res as any,
|
||||
db: null as any,
|
||||
session: session as any,
|
||||
user: user as any,
|
||||
},
|
||||
transformer: superjson,
|
||||
});
|
||||
await helpers.user.get.prefetch();
|
||||
try {
|
||||
await helpers.project.all.prefetch();
|
||||
await helpers.settings.isCloud.prefetch();
|
||||
if (user.role === "member") {
|
||||
const userR = await helpers.user.one.fetch({
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
if (!userR?.canAccessToGitProviders) {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
destination: "/",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
},
|
||||
};
|
||||
} catch (_error) {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
}
|
||||
if (!userR?.canAccessToGitProviders) {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
destination: "/",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
} catch (_error) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { api } from "@/utils/api";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { validateRequest } from "@dokploy/server";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
@@ -180,6 +181,7 @@ export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
const { user, session } = await validateRequest(ctx.req);
|
||||
if (!user) {
|
||||
return {
|
||||
@@ -214,6 +216,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ShowNotifications } from "@/components/dashboard/settings/notifications
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { validateRequest } from "@dokploy/server";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
@@ -25,6 +26,7 @@ export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
const { user, session } = await validateRequest(req);
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
@@ -52,6 +54,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["settings"])),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ShowRegistry } from "@/components/dashboard/settings/cluster/registry/s
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { serverSideTranslations, getLocale } from "@/utils/i18n";
|
||||
import { validateRequest } from "@dokploy/server";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
@@ -25,6 +26,7 @@ export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
const { user, session } = await validateRequest(req);
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
@@ -51,6 +53,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["settings"])),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["settings"])),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ShowDestinations } from "@/components/dashboard/settings/ssh-keys/show-
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { validateRequest } from "@dokploy/server";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
@@ -34,6 +35,7 @@ export async function getServerSideProps(
|
||||
};
|
||||
}
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
const helpers = createServerSideHelpers({
|
||||
router: appRouter,
|
||||
ctx: {
|
||||
@@ -67,11 +69,14 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
} catch (_error) {
|
||||
return {
|
||||
props: {},
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ShowUsers } from "@/components/dashboard/settings/users/show-users";
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
|
||||
import { appRouter } from "@/server/api/root";
|
||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||
import { validateRequest } from "@dokploy/server";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
@@ -27,6 +28,7 @@ export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const locale = await getLocale(req.cookies);
|
||||
const { user, session } = await validateRequest(req);
|
||||
|
||||
if (!user || user.role === "member") {
|
||||
@@ -55,6 +57,7 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
trpcState: helpers.dehydrate(),
|
||||
...(await serverSideTranslations(locale, ["common", "settings"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1 +1,37 @@
|
||||
{}
|
||||
{
|
||||
"common.side.home": "Home",
|
||||
"common.side.settings": "Settings",
|
||||
"common.side.extra": "Extra",
|
||||
|
||||
"common.side.projects": "Projects",
|
||||
"common.side.monitoring": "Monitoring",
|
||||
"common.side.traefik": "Traefik File System",
|
||||
"common.side.docker": "Docker",
|
||||
"common.side.swarm": "Swarm",
|
||||
"common.side.requests": "Requests",
|
||||
"common.side.web-server": "Web Server",
|
||||
"common.side.profile": "Profile",
|
||||
"common.side.remote-servers": "Remote Servers",
|
||||
"common.side.users": "Users",
|
||||
"common.side.ssh-keys": "SSH Keys",
|
||||
"common.side.ai": "AI",
|
||||
"common.side.git": "Git",
|
||||
"common.side.registry": "Registry",
|
||||
"common.side.s3-destinations": "S3 Destinations",
|
||||
"common.side.certificates": "Certificates",
|
||||
"common.side.cluster": "Cluster",
|
||||
"common.side.notifications": "Notifications",
|
||||
"common.side.billing": "Billing",
|
||||
"common.side.documentation": "Documentation",
|
||||
"common.side.support": "Support",
|
||||
"common.side.sponsor": "Sponsor",
|
||||
|
||||
"common.side.invitations.pending-invitations": "Pending Invitations",
|
||||
"common.side.invitations.no-pending-invitations": "No pending invitations",
|
||||
"common.side.invitations.accept-invitation": "Accept Invitation",
|
||||
"common.side.invitations.confirm-accept-invitation": "Are you sure you want to accept this invitation?",
|
||||
"common.side.invitations.error-accepting-invitation": "Error accepting invitation",
|
||||
"common.side.invitations.invitation-accepted": "Invitation accepted successfully",
|
||||
"common.side.invitations.expires": "Expires: {{expireDate}}",
|
||||
"common.side.invitations.role": "Role: {{role}}"
|
||||
}
|
||||
|
||||
@@ -1 +1,37 @@
|
||||
{}
|
||||
{
|
||||
"common.side.home": "主页",
|
||||
"common.side.settings": "设置",
|
||||
"common.side.extra": "其他",
|
||||
|
||||
"common.side.projects": "项目",
|
||||
"common.side.monitoring": "监控",
|
||||
"common.side.traefik": "Traefik",
|
||||
"common.side.docker": "Docker",
|
||||
"common.side.swarm": "Swarm",
|
||||
"common.side.requests": "请求",
|
||||
"common.side.web-server": "本地配置",
|
||||
"common.side.profile": "个人资料",
|
||||
"common.side.remote-servers": "远程服务器",
|
||||
"common.side.users": "用户",
|
||||
"common.side.ssh-keys": "SSH 密钥",
|
||||
"common.side.ai": "AI",
|
||||
"common.side.git": "Git 集成",
|
||||
"common.side.registry": "注册表",
|
||||
"common.side.s3-destinations": "S3 存储",
|
||||
"common.side.certificates": "证书",
|
||||
"common.side.cluster": "集群",
|
||||
"common.side.notifications": "通知",
|
||||
"common.side.billing": "账单",
|
||||
"common.side.documentation": "文档",
|
||||
"common.side.support": "支持",
|
||||
"common.side.sponsor": "赞助",
|
||||
|
||||
"common.side.invitations.pending-invitations": "待处理邀请",
|
||||
"common.side.invitations.no-pending-invitations": "没有待处理的邀请",
|
||||
"common.side.invitations.accept-invitation": "接受邀请",
|
||||
"common.side.invitations.confirm-accept-invitation": "您确定要接受此邀请吗?",
|
||||
"common.side.invitations.error-accepting-invitation": "接受邀请时出错",
|
||||
"common.side.invitations.invitation-accepted": "邀请已成功接受",
|
||||
"common.side.invitations.expires": "有效期:{{expireDate}}",
|
||||
"common.side.invitations.role": "角色:{{role}}"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user