mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat: add translate for zh-Hans
This commit is contained in:
25
apps/website/app/[locale]/page.tsx
Normal file
25
apps/website/app/[locale]/page.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { CallToAction } from '@/components/CallToAction'
|
||||
import { Faqs } from '@/components/Faqs'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Hero } from '@/components/Hero'
|
||||
import { PrimaryFeatures } from '@/components/PrimaryFeatures'
|
||||
import { SecondaryFeatures } from '@/components/SecondaryFeatures'
|
||||
import { Testimonials } from '../../components/Testimonials'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<PrimaryFeatures />
|
||||
<SecondaryFeatures />
|
||||
<CallToAction />
|
||||
{/* <Testimonials /> */}
|
||||
<Faqs />
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { CallToAction } from "../components/CallToAction";
|
||||
import { Faqs } from "../components/Faqs";
|
||||
import { Footer } from "../components/Footer";
|
||||
import { Header } from "../components/Header";
|
||||
import { Hero } from "../components/Hero";
|
||||
import { PrimaryFeatures } from "../components/PrimaryFeatures";
|
||||
import { SecondaryFeatures } from "../components/SecondaryFeatures";
|
||||
import { Testimonials } from "../components/Testimonials";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<PrimaryFeatures />
|
||||
<SecondaryFeatures />
|
||||
<CallToAction />
|
||||
{/* <Testimonials /> */}
|
||||
<Faqs />
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,63 +1,58 @@
|
||||
import { Container } from "./Container";
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { Container } from './Container'
|
||||
|
||||
const faqs = [
|
||||
[
|
||||
{
|
||||
question: "What is dokploy?",
|
||||
answer:
|
||||
"Dokploy is a stable, easy-to-use deployment solution designed to simplify the application management process. Think of Dokploy as a free alternative self-hostable solution to platforms like Heroku, Vercel, and Netlify.",
|
||||
question: 'faq.q1',
|
||||
answer: 'faq.a2',
|
||||
},
|
||||
{
|
||||
question: "Why Choose Dokploy?",
|
||||
answer: "Simplicity, Flexibility, and Fast",
|
||||
question: 'faq.q2',
|
||||
answer: 'faq.a2',
|
||||
},
|
||||
{
|
||||
question: "Is free?",
|
||||
answer:
|
||||
"Yes, dokploy is totally free. You can use it for personal projects, small teams, or even for large-scale applications.",
|
||||
question: 'faq.q3',
|
||||
answer: 'faq.a3',
|
||||
},
|
||||
{
|
||||
question: "Is it open source?",
|
||||
answer: "Yes, dokploy is open source and free to use.",
|
||||
question: 'faq.q4',
|
||||
answer: 'faq.a4',
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
question: "What type of applications can i deploy with dokploy?",
|
||||
answer:
|
||||
"Dokploy is a great choice for any type of application. You can deploy your code to dokploy and manage it from the dashboard. We support a wide range of languages and frameworks, so you can choose the one that best fits your needs.",
|
||||
question: 'faq.q5',
|
||||
answer: 'faq.a5',
|
||||
},
|
||||
{
|
||||
question: "How do I request a feature or report a bug?",
|
||||
answer:
|
||||
"Currently we are working on fixing bug fixes, but we will be releasing new features soon. You can also request features or report bugs.",
|
||||
question: 'faq.q6',
|
||||
answer: 'faq.a6',
|
||||
},
|
||||
{
|
||||
question: "Do you track the usage of Dokploy?",
|
||||
answer: "No, we don't track any usage data.",
|
||||
question: 'faq.q7',
|
||||
answer: "faq.a7",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
question:
|
||||
"Are there any user forums or communities where I can interact with other users?",
|
||||
answer:
|
||||
"Yes, we have active github discussions where you can share ideas, ask for help, and connect with other users.",
|
||||
'faq.q8',
|
||||
answer: 'faq.a8',
|
||||
},
|
||||
{
|
||||
question: "What types of applications can I deploy with Dokploy?",
|
||||
answer:
|
||||
"Dokploy supports a variety of applications, including those built with Docker, as well as applications from any Git repository, offering custom builds with Nixpacks, Dockerfiles, or Buildpacks like Heroku and Paketo.",
|
||||
question: 'faq.q9',
|
||||
answer: 'faq.a9',
|
||||
},
|
||||
{
|
||||
question: "How does Dokploy handle database management?",
|
||||
answer:
|
||||
"Dokploy supports multiple database systems including Postgres, MySQL, MariaDB, MongoDB, and Redis, providing tools for easy deployment and management directly from the dashboard.",
|
||||
question: 'faq.q10',
|
||||
answer: 'faq.a10',
|
||||
},
|
||||
],
|
||||
];
|
||||
]
|
||||
|
||||
export function Faqs() {
|
||||
const t = useTranslations('HomePage')
|
||||
return (
|
||||
<section
|
||||
id="faqs"
|
||||
@@ -70,11 +65,10 @@ export function Faqs() {
|
||||
id="faq-title"
|
||||
className="font-display text-3xl tracking-tight text-primary sm:text-4xl"
|
||||
>
|
||||
Frequently asked questions
|
||||
{t('faq.title')}
|
||||
</h2>
|
||||
<p className="mt-4 text-lg tracking-tight text-muted-foreground">
|
||||
If you can’t find what you’re looking for, email our support team
|
||||
and if you’re lucky someone will get back to you.
|
||||
{t('faq.des')}
|
||||
</p>
|
||||
</div>
|
||||
<ul className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-8 lg:max-w-none lg:grid-cols-3">
|
||||
@@ -84,10 +78,10 @@ export function Faqs() {
|
||||
{column.map((faq, faqIndex) => (
|
||||
<li key={faqIndex}>
|
||||
<h3 className="font-display text-lg leading-7 text-primary">
|
||||
{faq.question}
|
||||
{t(faq.question)}
|
||||
</h3>
|
||||
<p className="mt-4 text-sm text-muted-foreground">
|
||||
{faq.answer}
|
||||
{t(faq.answer)}
|
||||
</p>
|
||||
</li>
|
||||
))}
|
||||
@@ -97,5 +91,5 @@ export function Faqs() {
|
||||
</ul>
|
||||
</Container>
|
||||
</section>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import Link from "next/link";
|
||||
import Link from 'next/link'
|
||||
|
||||
import { Container } from "./Container";
|
||||
import { NavLink } from "./NavLink";
|
||||
import { Logo } from "./shared/Logo";
|
||||
import { Container } from './Container'
|
||||
import { NavLink } from './NavLink'
|
||||
import { Logo } from './shared/Logo'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
export function Footer() {
|
||||
const t = useTranslations('HomePage')
|
||||
return (
|
||||
<footer className="bg-black">
|
||||
<Container>
|
||||
<div className="py-16">
|
||||
<div className="flex flex-col gap-2 items-center">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<Logo className="mx-auto h-10 w-auto" />
|
||||
<span className="text-center text-sm font-medium text-primary">
|
||||
Dokploy
|
||||
@@ -17,14 +19,18 @@ export function Footer() {
|
||||
</div>
|
||||
|
||||
<nav className="mt-10 text-sm" aria-label="quick links">
|
||||
<div className="-my-1 flex justify-center gap-6 flex-wrap">
|
||||
<NavLink href="/#features">Features</NavLink>
|
||||
<NavLink href="/#faqs">Faqs</NavLink>
|
||||
<div className="-my-1 flex flex-wrap justify-center gap-6">
|
||||
<NavLink href="/#features">
|
||||
{t('navigation.features')}
|
||||
</NavLink>
|
||||
<NavLink href="/#faqs">
|
||||
{t('navigation.faqs')}
|
||||
</NavLink>
|
||||
<NavLink
|
||||
href="https://docs.dokploy.com/get-started/introduction"
|
||||
target="_blank"
|
||||
>
|
||||
Docs
|
||||
{t('navigation.docs')}
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -57,11 +63,12 @@ export function Footer() {
|
||||
</Link>
|
||||
</div>
|
||||
<p className="mt-6 text-sm text-muted-foreground sm:mt-0">
|
||||
Copyright © {new Date().getFullYear()} Dokploy. All rights
|
||||
reserved.
|
||||
{t('footer.copyright', {
|
||||
year: new Date().getFullYear(),
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
</Container>
|
||||
</footer>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
"use client";
|
||||
'use client'
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
import { HeartIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { Fragment } from "react";
|
||||
import { Container } from "./Container";
|
||||
import { NavLink } from "./NavLink";
|
||||
import { trackGAEvent } from "./analitycs";
|
||||
import { Logo } from "./shared/Logo";
|
||||
import { Button, buttonVariants } from "./ui/button";
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Popover, Transition } from '@headlessui/react'
|
||||
import { HeartIcon } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { Fragment } from 'react'
|
||||
import { Container } from './Container'
|
||||
import { NavLink } from './NavLink'
|
||||
import { trackGAEvent } from './analitycs'
|
||||
import { Logo } from './shared/Logo'
|
||||
import { Button, buttonVariants } from './ui/button'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
function MobileNavLink({
|
||||
href,
|
||||
children,
|
||||
target,
|
||||
}: {
|
||||
href: string;
|
||||
children: React.ReactNode;
|
||||
target?: string;
|
||||
href: string
|
||||
children: React.ReactNode
|
||||
target?: string
|
||||
}) {
|
||||
return (
|
||||
<Popover.Button
|
||||
onClick={() => {
|
||||
trackGAEvent({
|
||||
action: "Nav Link Clicked",
|
||||
category: "Navigation",
|
||||
action: 'Nav Link Clicked',
|
||||
category: 'Navigation',
|
||||
label: href,
|
||||
});
|
||||
})
|
||||
}}
|
||||
as={Link}
|
||||
href={href}
|
||||
@@ -36,7 +37,7 @@ function MobileNavLink({
|
||||
>
|
||||
{children}
|
||||
</Popover.Button>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function MobileNavIcon({ open }: { open: boolean }) {
|
||||
@@ -50,20 +51,24 @@ function MobileNavIcon({ open }: { open: boolean }) {
|
||||
>
|
||||
<path
|
||||
d="M0 1H14M0 7H14M0 13H14"
|
||||
className={cn("origin-center transition", open && "scale-90 opacity-0")}
|
||||
className={cn(
|
||||
'origin-center transition',
|
||||
open && 'scale-90 opacity-0',
|
||||
)}
|
||||
/>
|
||||
<path
|
||||
d="M2 2L12 12M12 2L2 12"
|
||||
className={cn(
|
||||
"origin-center transition",
|
||||
!open && "scale-90 opacity-0",
|
||||
'origin-center transition',
|
||||
!open && 'scale-90 opacity-0',
|
||||
)}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function MobileNavigation() {
|
||||
const t = useTranslations('HomePage')
|
||||
return (
|
||||
<Popover>
|
||||
<Popover.Button
|
||||
@@ -96,27 +101,32 @@ function MobileNavigation() {
|
||||
>
|
||||
<Popover.Panel
|
||||
as="div"
|
||||
className="absolute inset-x-0 top-full mt-4 flex origin-top flex-col rounded-2xl bg-background border border-border p-4 text-lg tracking-tight text-primary shadow-xl ring-1 ring-border/5"
|
||||
className="absolute inset-x-0 top-full mt-4 flex origin-top flex-col rounded-2xl border border-border bg-background p-4 text-lg tracking-tight text-primary shadow-xl ring-1 ring-border/5"
|
||||
>
|
||||
<MobileNavLink href="/#features">Features</MobileNavLink>
|
||||
<MobileNavLink href="/#testimonials">Testimonials</MobileNavLink>
|
||||
<MobileNavLink href="/#faqs">Faqs</MobileNavLink>
|
||||
<MobileNavLink href="/#features">
|
||||
{t('navigation.features')}
|
||||
</MobileNavLink>
|
||||
{/* <MobileNavLink href="/#testimonials">Testimonials</MobileNavLink> */}
|
||||
<MobileNavLink href="/#faqs">
|
||||
{t('navigation.faqs')}
|
||||
</MobileNavLink>
|
||||
<MobileNavLink
|
||||
href="https://docs.dokploy.com/get-started/introduction"
|
||||
target="_blank"
|
||||
>
|
||||
Docs
|
||||
{t('navigation.docs')}
|
||||
</MobileNavLink>
|
||||
</Popover.Panel>
|
||||
</Transition.Child>
|
||||
</Transition.Root>
|
||||
</Popover>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export function Header() {
|
||||
const t = useTranslations('HomePage')
|
||||
return (
|
||||
<header className="py-10 bg-background">
|
||||
<header className="bg-background py-10">
|
||||
<Container>
|
||||
<nav className="relative z-50 flex justify-between">
|
||||
<div className="flex items-center md:gap-x-12">
|
||||
@@ -124,28 +134,35 @@ export function Header() {
|
||||
<Logo className="h-10 w-auto" />
|
||||
</Link>
|
||||
<div className="hidden md:flex md:gap-x-6">
|
||||
<NavLink href="/#features">Features</NavLink>
|
||||
<NavLink href="/#features">
|
||||
{t('navigation.features')}
|
||||
</NavLink>
|
||||
{/* <NavLink href="/#testimonials">Testimonials</NavLink> */}
|
||||
<NavLink href="/#faqs">Faqs</NavLink>
|
||||
<NavLink href="/#faqs">
|
||||
{t('navigation.faqs')}
|
||||
</NavLink>
|
||||
<NavLink
|
||||
href="https://docs.dokploy.com/get-started/introduction"
|
||||
target="_blank"
|
||||
>
|
||||
Docs
|
||||
{t('navigation.docs')}
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-x-2 md:gap-x-5">
|
||||
<Link
|
||||
className={buttonVariants({
|
||||
variant: "outline",
|
||||
className: " flex items-center gap-2 !rounded-full",
|
||||
variant: 'outline',
|
||||
className:
|
||||
' flex items-center gap-2 !rounded-full',
|
||||
})}
|
||||
href="https://opencollective.com/dokploy"
|
||||
target="_blank"
|
||||
>
|
||||
<span className="text-sm font-semibold">Support </span>
|
||||
<HeartIcon className="size-4 text-red-500 fill-red-600 animate-heartbeat " />
|
||||
<span className="text-sm font-semibold">
|
||||
{t('navigation.support')}{' '}
|
||||
</span>
|
||||
<HeartIcon className="animate-heartbeat size-4 fill-red-600 text-red-500 " />
|
||||
</Link>
|
||||
{/* @ts-expect-error */}
|
||||
<Button
|
||||
@@ -156,7 +173,7 @@ export function Header() {
|
||||
href="https://discord.gg/2tBnJ3jDJc"
|
||||
aria-label="Dokploy on GitHub"
|
||||
target="_blank"
|
||||
className="flex flex-row gap-2 items-center text-white"
|
||||
className="flex flex-row items-center gap-2 text-white"
|
||||
>
|
||||
<svg
|
||||
role="img"
|
||||
@@ -166,7 +183,7 @@ export function Header() {
|
||||
>
|
||||
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z" />
|
||||
</svg>
|
||||
Discord
|
||||
{t('navigation.discord')}
|
||||
</Link>
|
||||
</Button>
|
||||
<div className="-mr-1 md:hidden">
|
||||
@@ -176,5 +193,5 @@ export function Header() {
|
||||
</nav>
|
||||
</Container>
|
||||
</header>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,77 +1,73 @@
|
||||
"use client";
|
||||
'use client'
|
||||
|
||||
import { Tab } from "@headlessui/react";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Tab } from '@headlessui/react'
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Container } from "./Container";
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Container } from './Container'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
const features = [
|
||||
{
|
||||
title: "Projects",
|
||||
description:
|
||||
"Manage and organize all your projects in one place, keeping detailed track of progress and resource allocation.",
|
||||
image: "/primary/projects.png",
|
||||
title: 'primaryFeatures.projects',
|
||||
description: 'primaryFeatures.projectsDes',
|
||||
image: '/primary/projects.png',
|
||||
},
|
||||
{
|
||||
title: "Applications & Databases",
|
||||
description:
|
||||
"Centralize control over your applications and databases for enhanced security and efficiency, simplifying access and management across your infrastructure.",
|
||||
image: "/primary/applications.png",
|
||||
title: 'primaryFeatures.applications',
|
||||
description: 'primaryFeatures.applicationsDes',
|
||||
image: '/primary/applications.png',
|
||||
},
|
||||
{
|
||||
title: "Docker Compose",
|
||||
description:
|
||||
"Native Docker Compose support for manage complex applications and services with ease.",
|
||||
image: "/primary/compose.png",
|
||||
title: 'primaryFeatures.compose',
|
||||
description: 'primaryFeatures.composeDes',
|
||||
image: '/primary/compose.png',
|
||||
},
|
||||
{
|
||||
title: "Multi Node",
|
||||
description:
|
||||
"Scale applications to multiples nodes using docker swarm to manage the cluster.",
|
||||
image: "/primary/multinode.png",
|
||||
title: 'primaryFeatures.multinode',
|
||||
description: 'primaryFeatures.multinodeDes',
|
||||
image: '/primary/multinode.png',
|
||||
},
|
||||
{
|
||||
title: "Monitoring",
|
||||
description:
|
||||
"Monitor your systems' performance and health in real time, ensuring continuous and uninterrupted operation.",
|
||||
image: "/primary/monitoring.png",
|
||||
title: 'primaryFeatures.monitoring',
|
||||
description: 'primaryFeatures.monitoringDes',
|
||||
image: '/primary/monitoring.png',
|
||||
},
|
||||
{
|
||||
title: "Backups",
|
||||
description:
|
||||
"Implement automatic and secure backup solutions to protect your critical data and restore it quickly when necessary.",
|
||||
image: "/primary/backups.png",
|
||||
title: 'primaryFeatures.backups',
|
||||
description: 'primaryFeatures.backupsDes',
|
||||
image: '/primary/backups.png',
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
export function PrimaryFeatures() {
|
||||
const t = useTranslations('HomePage')
|
||||
const [tabOrientation, setTabOrientation] = useState<
|
||||
"horizontal" | "vertical"
|
||||
>("horizontal");
|
||||
'horizontal' | 'vertical'
|
||||
>('horizontal')
|
||||
|
||||
useEffect(() => {
|
||||
const lgMediaQuery = window.matchMedia("(min-width: 1024px)");
|
||||
const lgMediaQuery = window.matchMedia('(min-width: 1024px)')
|
||||
|
||||
function onMediaQueryChange({ matches }: { matches: boolean }) {
|
||||
setTabOrientation(matches ? "vertical" : "horizontal");
|
||||
setTabOrientation(matches ? 'vertical' : 'horizontal')
|
||||
}
|
||||
|
||||
onMediaQueryChange(lgMediaQuery);
|
||||
lgMediaQuery.addEventListener("change", onMediaQueryChange);
|
||||
onMediaQueryChange(lgMediaQuery)
|
||||
lgMediaQuery.addEventListener('change', onMediaQueryChange)
|
||||
|
||||
return () => {
|
||||
lgMediaQuery.removeEventListener("change", onMediaQueryChange);
|
||||
};
|
||||
}, []);
|
||||
lgMediaQuery.removeEventListener('change', onMediaQueryChange)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
const [isMounted, setIsMounted] = useState(false)
|
||||
|
||||
// Cambiar isMounted a true después del primer render
|
||||
useEffect(() => {
|
||||
setIsMounted(true);
|
||||
}, []);
|
||||
setIsMounted(true)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<section
|
||||
@@ -92,17 +88,16 @@ export function PrimaryFeatures() {
|
||||
<Container className="relative">
|
||||
<div className="max-w-2xl md:mx-auto md:text-center xl:max-w-none">
|
||||
<h2 className="font-display text-3xl tracking-tight text-white sm:text-4xl md:text-5xl">
|
||||
Comprehensive Control for Your Digital Ecosystem
|
||||
{t('primaryFeatures.title')}
|
||||
</h2>
|
||||
<p className="mt-6 text-lg tracking-tight text-muted-foreground">
|
||||
Simplify your project and data management, ensure robust monitoring,
|
||||
and secure your backups—all without the fuss over minute details.
|
||||
{t('primaryFeatures.des')}
|
||||
</p>
|
||||
</div>
|
||||
<Tab.Group
|
||||
as="div"
|
||||
className="mt-16 grid grid-cols-1 items-center gap-y-2 pt-10 sm:gap-y-6 md:mt-20 lg:grid-cols-12 lg:pt-0"
|
||||
vertical={tabOrientation === "vertical"}
|
||||
vertical={tabOrientation === 'vertical'}
|
||||
>
|
||||
{({ selectedIndex }) => (
|
||||
<>
|
||||
@@ -118,19 +113,20 @@ export function PrimaryFeatures() {
|
||||
initial={false}
|
||||
key={`feature-${featureIndex}`}
|
||||
className={cn(
|
||||
"group relative rounded-full px-4 py-1 lg:rounded-l-xl lg:rounded-r-none lg:p-6 transition-colors ",
|
||||
'group relative rounded-full px-4 py-1 transition-colors lg:rounded-l-xl lg:rounded-r-none lg:p-6 ',
|
||||
)}
|
||||
>
|
||||
<AnimatePresence>
|
||||
{selectedIndex === featureIndex && (
|
||||
{selectedIndex ===
|
||||
featureIndex && (
|
||||
<motion.span
|
||||
layoutId="tab"
|
||||
className="absolute inset-0 z-10 bg-white/5 rounded-full mix-blend-difference lg:rounded-l-xl lg:rounded-r-none"
|
||||
className="absolute inset-0 z-10 rounded-full bg-white/5 mix-blend-difference lg:rounded-l-xl lg:rounded-r-none"
|
||||
initial={{ opacity: 1 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{
|
||||
type: "spring",
|
||||
type: 'spring',
|
||||
bounce: 0.2,
|
||||
duration: 0.5,
|
||||
}}
|
||||
@@ -140,19 +136,19 @@ export function PrimaryFeatures() {
|
||||
<h3>
|
||||
<Tab
|
||||
className={cn(
|
||||
"font-display text-lg ui-not-focus-visible:outline-none text-primary",
|
||||
'font-display text-lg text-primary ui-not-focus-visible:outline-none',
|
||||
)}
|
||||
>
|
||||
<span className="absolute inset-0 rounded-full lg:rounded-l-xl lg:rounded-r-none" />
|
||||
{feature.title}
|
||||
{t(feature.title)}
|
||||
</Tab>
|
||||
</h3>
|
||||
<p
|
||||
className={cn(
|
||||
"mt-2 hidden text-sm lg:block text-muted-foreground",
|
||||
'mt-2 hidden text-sm text-muted-foreground lg:block',
|
||||
)}
|
||||
>
|
||||
{feature.description}
|
||||
{t(feature.description)}
|
||||
</p>
|
||||
</motion.div>
|
||||
))}
|
||||
@@ -164,21 +160,29 @@ export function PrimaryFeatures() {
|
||||
<div className="relative sm:px-6 lg:hidden">
|
||||
<div className="absolute -inset-x-4 bottom-[-4.25rem] top-[-6.5rem] bg-white/10 ring-1 ring-inset ring-white/10 sm:inset-x-0 sm:rounded-t-xl" />
|
||||
<p className="relative mx-auto max-w-2xl text-base text-white sm:text-center">
|
||||
{feature.description}
|
||||
{t(feature.description)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
key={feature.title}
|
||||
initial={isMounted ? { opacity: 0.8, x: 50 } : {}}
|
||||
animate={isMounted ? { opacity: 1, x: 0 } : {}}
|
||||
initial={
|
||||
isMounted
|
||||
? { opacity: 0.8, x: 50 }
|
||||
: {}
|
||||
}
|
||||
animate={
|
||||
isMounted
|
||||
? { opacity: 1, x: 0 }
|
||||
: {}
|
||||
}
|
||||
exit={{ opacity: 0, x: -50 }}
|
||||
transition={{
|
||||
type: "spring",
|
||||
type: 'spring',
|
||||
bounce: 0.2,
|
||||
duration: 0.6,
|
||||
}}
|
||||
className="mt-10 h-[24rem] lg:h-[40rem] w-[45rem] overflow-hidden rounded-xl shadow-xl border sm:w-auto lg:mt-0 lg:w-[67.8125rem]"
|
||||
className="mt-10 h-[24rem] w-[45rem] overflow-hidden rounded-xl border shadow-xl sm:w-auto lg:mt-0 lg:h-[40rem] lg:w-[67.8125rem]"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
@@ -195,5 +199,5 @@ export function PrimaryFeatures() {
|
||||
</Tab.Group>
|
||||
</Container>
|
||||
</section>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,40 +1,38 @@
|
||||
"use client";
|
||||
'use client'
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Tab } from "@headlessui/react";
|
||||
import { motion } from "framer-motion";
|
||||
import { Layers, Terminal, Users } from "lucide-react";
|
||||
import { Container } from "./Container";
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Tab } from '@headlessui/react'
|
||||
import { motion } from 'framer-motion'
|
||||
import { Layers, Terminal, Users } from 'lucide-react'
|
||||
import { Container } from './Container'
|
||||
import { useTranslations } from 'next-intl'
|
||||
interface Feature {
|
||||
name: React.ReactNode;
|
||||
summary: string;
|
||||
description: string;
|
||||
image: string;
|
||||
icon: React.ComponentType;
|
||||
name: React.ReactNode
|
||||
summary: string
|
||||
description: string
|
||||
image: string
|
||||
icon: React.ComponentType
|
||||
}
|
||||
|
||||
const features: Array<Feature> = [
|
||||
{
|
||||
name: "Open Source Templates",
|
||||
summary: "One click to deploy open source templates.",
|
||||
description:
|
||||
"Deploy open source templates with one click, powered by Docker Compose, (Plausible, Calcom, Pocketbase, etc.)",
|
||||
image: "/secondary/templates.png",
|
||||
name: 'secondaryFeatures.templates',
|
||||
summary: 'secondaryFeatures.templatesSummary',
|
||||
description: 'secondaryFeatures.templatesDes',
|
||||
image: '/secondary/templates.png',
|
||||
icon: function ReportingIcon() {
|
||||
return (
|
||||
<>
|
||||
<Layers className="size-5 text-primary" />
|
||||
</>
|
||||
);
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Real-Time Traefik Configuration",
|
||||
summary:
|
||||
" Modify Traefik settings on-the-fly via a graphical interface or API.",
|
||||
description:
|
||||
"Users can adjust Traefik's configuration, including middleware, forwarding rules, and SSL certificates through an intuitive interface or API. This feature enables seamless traffic routing and security adjustments without the need to restart services",
|
||||
image: "/secondary/traefik.png",
|
||||
name: 'secondaryFeatures.traefik',
|
||||
summary: 'secondaryFeatures.traefikSummary',
|
||||
description: 'secondaryFeatures.traefikDes',
|
||||
image: '/secondary/traefik.png',
|
||||
icon: function ReportingIcon() {
|
||||
return (
|
||||
<>
|
||||
@@ -84,7 +82,12 @@ const features: Array<Feature> = [
|
||||
d="M299.847 285.567c10.027 58.288 105.304 42.877 91.619-15.91-12.271-52.716-94.951-38.124-91.619 15.91m-113.855 9.427c12.996 50.745 94.24 37.753 91.178-13.149-3.669-60.964-103.603-49.2-91.178 13.149m132.351 58.517c.044 7.79 1.843 15.403.289 24.148-1.935 3.656-5.729 4.043-9.001 5.52-4.524-.71-8.328-3.68-10.143-7.912-1.161-9.202.433-18.111.726-27.316l18.129 5.56z"
|
||||
fill="#fff"
|
||||
/>
|
||||
<ellipse cx="208.4" cy="286.718" rx="13.719" ry="14.86" />
|
||||
<ellipse
|
||||
cx="208.4"
|
||||
cy="286.718"
|
||||
rx="13.719"
|
||||
ry="14.86"
|
||||
/>
|
||||
<ellipse
|
||||
cx="214.64"
|
||||
cy="290.071"
|
||||
@@ -92,9 +95,19 @@ const features: Array<Feature> = [
|
||||
ry="3.777"
|
||||
fill="#fff"
|
||||
/>
|
||||
<ellipse cx="323.348" cy="283.017" rx="13.491" ry="14.86" />
|
||||
<ellipse
|
||||
cx="323.348"
|
||||
cy="283.017"
|
||||
rx="13.491"
|
||||
ry="14.86"
|
||||
/>
|
||||
<g fill="#fff">
|
||||
<ellipse cx="329.485" cy="286.371" rx="3.181" ry="3.777" />
|
||||
<ellipse
|
||||
cx="329.485"
|
||||
cy="286.371"
|
||||
rx="3.181"
|
||||
ry="3.777"
|
||||
/>
|
||||
<path d="M279.137 354.685c-5.986 14.507 3.338 43.515 19.579 22.119-1.161-9.202.433-18.111.726-27.316l-20.305 5.197z" />
|
||||
</g>
|
||||
<path
|
||||
@@ -213,63 +226,60 @@ const features: Array<Feature> = [
|
||||
</g>
|
||||
</svg>
|
||||
</>
|
||||
);
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "User Permission Management",
|
||||
summary:
|
||||
"Detailed control over user permissions for accessing and managing projects and services.",
|
||||
description:
|
||||
"Allows administrators to define specific roles and permissions for each user, including the ability to create, modify, or delete applications and databases. This feature ensures secure and efficient management of large and diverse teams.",
|
||||
image: "/secondary/users.png",
|
||||
name: 'secondaryFeatures.users',
|
||||
summary: 'secondaryFeatures.usersSummary',
|
||||
description: 'secondaryFeatures.usersDes',
|
||||
image: '/secondary/users.png',
|
||||
icon: function InventoryIcon() {
|
||||
return (
|
||||
<>
|
||||
<Users className="size-5 text-primary" />
|
||||
</>
|
||||
);
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Terminal Access",
|
||||
summary:
|
||||
"Direct access to each container's and server terminal for advanced management.",
|
||||
description:
|
||||
"Provides an interface to access the command line of any active container, allowing developers to execute commands, manage services, and troubleshoot directly from the dashboard",
|
||||
image: "/secondary/terminal.png",
|
||||
name: 'secondaryFeatures.terminal',
|
||||
summary: 'secondaryFeatures.terminalSummary',
|
||||
description: 'secondaryFeatures.terminalDes',
|
||||
image: '/secondary/terminal.png',
|
||||
icon: function ContactsIcon() {
|
||||
return (
|
||||
<>
|
||||
<Terminal className="size-5 text-primary" />
|
||||
</>
|
||||
);
|
||||
)
|
||||
},
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
function Feature({
|
||||
feature,
|
||||
isActive,
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentPropsWithoutRef<"div"> & {
|
||||
feature: Feature;
|
||||
isActive: boolean;
|
||||
}: React.ComponentPropsWithoutRef<'div'> & {
|
||||
feature: Feature
|
||||
isActive: boolean
|
||||
}) {
|
||||
const t = useTranslations('HomePage')
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
className,
|
||||
!isActive ? "opacity-75 hover:opacity-100 " : "rounded-xl",
|
||||
" p-4 relative",
|
||||
!isActive ? 'opacity-75 hover:opacity-100 ' : 'rounded-xl',
|
||||
' relative p-4',
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"size-9 rounded-lg flex items-center justify-center",
|
||||
isActive ? "bg-border" : "bg-muted",
|
||||
'flex size-9 items-center justify-center rounded-lg',
|
||||
isActive ? 'bg-border' : 'bg-muted',
|
||||
)}
|
||||
>
|
||||
<feature.icon />
|
||||
@@ -277,9 +287,9 @@ function Feature({
|
||||
{isActive && (
|
||||
<motion.span
|
||||
layoutId="bubble"
|
||||
className="absolute inset-0 z-10 bg-white/5 mix-blend-difference rounded-xl"
|
||||
className="absolute inset-0 z-10 rounded-xl bg-white/5 mix-blend-difference"
|
||||
transition={{
|
||||
type: "spring",
|
||||
type: 'spring',
|
||||
bounce: 0.2,
|
||||
duration: 0.6,
|
||||
}}
|
||||
@@ -287,20 +297,20 @@ function Feature({
|
||||
)}
|
||||
<h3
|
||||
className={cn(
|
||||
"mt-6 text-sm font-medium",
|
||||
isActive ? "text-primary" : "text-primary/85",
|
||||
'mt-6 text-sm font-medium',
|
||||
isActive ? 'text-primary' : 'text-primary/85',
|
||||
)}
|
||||
>
|
||||
{feature.name}
|
||||
</h3>
|
||||
<p className="mt-2 font-display text-xl text-foreground">
|
||||
{feature.summary}
|
||||
{t(feature.summary)}
|
||||
</p>
|
||||
<p className="mt-4 text-sm text-muted-foreground">
|
||||
{feature.description}
|
||||
{t(feature.description)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function FeaturesMobile() {
|
||||
@@ -308,7 +318,11 @@ function FeaturesMobile() {
|
||||
<div className="-mx-4 mt-20 flex flex-col gap-y-10 overflow-hidden px-4 sm:-mx-6 sm:px-6 lg:hidden">
|
||||
{features.map((feature) => (
|
||||
<div key={feature.summary}>
|
||||
<Feature feature={feature} className="mx-auto max-w-2xl" isActive />
|
||||
<Feature
|
||||
feature={feature}
|
||||
className="mx-auto max-w-2xl"
|
||||
isActive
|
||||
/>
|
||||
<div className="relative mt-10 pb-10">
|
||||
<div className="absolute -inset-x-4 bottom-0 top-8 bg-muted sm:-inset-x-6" />
|
||||
<div className="relative mx-auto w-[52.75rem] overflow-hidden rounded-xl bg-white shadow-lg shadow-slate-900/5 ring-1 ring-slate-500/10">
|
||||
@@ -323,10 +337,11 @@ function FeaturesMobile() {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
function FeaturesDesktop() {
|
||||
const t = useTranslations('HomePage')
|
||||
return (
|
||||
<Tab.Group as="div" className="hidden lg:mt-20 lg:block">
|
||||
{({ selectedIndex }) => (
|
||||
@@ -340,7 +355,7 @@ function FeaturesDesktop() {
|
||||
name: (
|
||||
<Tab className="ui-not-focus-visible:outline-none">
|
||||
<span className="absolute inset-0" />
|
||||
{feature.name}
|
||||
{t(feature.name)}
|
||||
</Tab>
|
||||
),
|
||||
}}
|
||||
@@ -356,10 +371,13 @@ function FeaturesDesktop() {
|
||||
static
|
||||
key={feature.summary}
|
||||
className={cn(
|
||||
"px-5 transition duration-500 ease-in-out ui-not-focus-visible:outline-none",
|
||||
featureIndex !== selectedIndex && "opacity-60",
|
||||
'px-5 transition duration-500 ease-in-out ui-not-focus-visible:outline-none',
|
||||
featureIndex !== selectedIndex &&
|
||||
'opacity-60',
|
||||
)}
|
||||
style={{ transform: `translateX(-${selectedIndex * 100}%)` }}
|
||||
style={{
|
||||
transform: `translateX(-${selectedIndex * 100}%)`,
|
||||
}}
|
||||
aria-hidden={featureIndex !== selectedIndex}
|
||||
>
|
||||
<div className="w-[52.75rem] overflow-hidden rounded-xl bg-red-500 shadow-lg shadow-slate-900/5 ring-1 ring-slate-500/10">
|
||||
@@ -378,30 +396,29 @@ function FeaturesDesktop() {
|
||||
</>
|
||||
)}
|
||||
</Tab.Group>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export function SecondaryFeatures() {
|
||||
const t = useTranslations('HomePage')
|
||||
return (
|
||||
<section
|
||||
id="secondary-features"
|
||||
aria-label="Features for simplifying everyday business tasks"
|
||||
className="pb-14 pt-20 sm:pb-20 sm:pt-32 lg:pb-32 bg-black"
|
||||
className="bg-black pb-14 pt-20 sm:pb-20 sm:pt-32 lg:pb-32"
|
||||
>
|
||||
<Container className="max-w-[95rem]">
|
||||
<div className="mx-auto max-w-2xl md:text-center">
|
||||
<h2 className="font-display text-3xl tracking-tight text-primary sm:text-4xl">
|
||||
Advanced Management Tools
|
||||
{t('secondaryFeatures.title')}
|
||||
</h2>
|
||||
<p className="mt-4 text-lg tracking-tight text-muted-foreground">
|
||||
Elevate your infrastructure with tools that offer precise control,
|
||||
detailed monitoring, and enhanced security, ensuring seamless
|
||||
management and robust performance.
|
||||
{t('secondaryFeatures.des')}
|
||||
</p>
|
||||
</div>
|
||||
<FeaturesMobile />
|
||||
<FeaturesDesktop />
|
||||
</Container>
|
||||
</section>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { Footer } from "./Footer";
|
||||
import { Header } from "./Header";
|
||||
import Link from 'next/link'
|
||||
import { Footer } from './Footer'
|
||||
import { Header } from './Header'
|
||||
|
||||
export function SlimLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
@@ -8,14 +8,16 @@ export function SlimLayout({ children }: { children: React.ReactNode }) {
|
||||
<div>
|
||||
<Header />
|
||||
</div>
|
||||
<main className="text-center flex-auto items-center flex justify-center">
|
||||
<main className="flex flex-auto items-center justify-center text-center">
|
||||
<div>
|
||||
<h1 className="mb-4 text-6xl font-semibold text-primary">404</h1>
|
||||
<h1 className="mb-4 text-6xl font-semibold text-primary">
|
||||
404
|
||||
</h1>
|
||||
<p className="mb-4 text-lg text-muted-foreground">
|
||||
Oops! Looks like you're lost.
|
||||
</p>
|
||||
<p className="mt-4 text-muted-foreground">
|
||||
Let's get you back{" "}
|
||||
Let's get you back{' '}
|
||||
<Link href="/" className="text-primary">
|
||||
home
|
||||
</Link>
|
||||
@@ -27,5 +29,5 @@ export function SlimLayout({ children }: { children: React.ReactNode }) {
|
||||
<Footer />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
82
apps/website/locales/en.json
Normal file
82
apps/website/locales/en.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"HomePage": {
|
||||
"navigation": {
|
||||
"features": "Features",
|
||||
"faqs": "FAQ",
|
||||
"docs": "Docs",
|
||||
"support": "Support",
|
||||
"discord": "Discord"
|
||||
},
|
||||
"hero": {
|
||||
"deploy": "Deploy",
|
||||
"anywhere": "Anywhere",
|
||||
"with": "with Total Freedom and Ease.",
|
||||
"des": "Streamline your operations with our all-in-one platform—perfect for managing projects, data, and system health with simplicity and efficiency.",
|
||||
"featuredIn": "Featured in"
|
||||
},
|
||||
"primaryFeatures": {
|
||||
"title": "Comprehensive Control for Your Digital Ecosystem",
|
||||
"des": "Simplify your project and data management, ensure robust monitoring, and secure your backups—all without the fuss over minute details.",
|
||||
"projects": "Projects",
|
||||
"projectsDes": "Manage and organize all your projects in one place, keeping detailed track of progress and resource allocation.",
|
||||
"applications": "Applications & Databases",
|
||||
"applicationsDes": "Centralize control over your applications and databases for enhanced security and efficiency, simplifying access and management across your infrastructure.",
|
||||
"compose": "compose",
|
||||
"composeDes": "Native Docker Compose support for manage complex applications and services with ease.",
|
||||
"multinode": "multinode",
|
||||
"multinodeDes": "Scale applications to multiples nodes using docker swarm to manage the cluster.",
|
||||
"monitoring": "Monitoring",
|
||||
"monitoringDes": "Monitor your systems' performance and health in real time, ensuring continuous and uninterrupted operation.",
|
||||
"backups": "Backups",
|
||||
"backupsDes": "Implement automatic and secure backup solutions to protect your critical data and restore it quickly when necessary."
|
||||
},
|
||||
"secondaryFeatures": {
|
||||
"title": "Advanced Management Tools",
|
||||
"des": "Elevate your infrastructure with tools that offer precise control, detailed monitoring, and enhanced security, ensuring seamless management and robust performance.",
|
||||
"templates": "Open Source Templates",
|
||||
"templatesSummary": "One click to deploy open source templates.",
|
||||
"templatesDes": "Deploy open source templates with one click, powered by Docker Compose, (Plausible, Calcom, Pocketbase, etc.)",
|
||||
"traefik": "Real-Time Traefik Configuration",
|
||||
"traefikSummary": "Modify Traefik settings on-the-fly via a graphical interface or API.",
|
||||
"traefikDes": "Users can adjust Traefik's configuration, including middleware, forwarding rules, and SSL certificates through an intuitive interface or API. This feature enables seamless traffic routing and security adjustments without the need to restart services",
|
||||
"users": "User Permission Management",
|
||||
"usersSummary": "Detailed control over user permissions for accessing and managing projects and services.",
|
||||
"usersDes": "Allows administrators to define specific roles and permissions for each user, including the ability to create, modify, or delete applications and databases. This feature ensures secure and efficient management of large and diverse teams.",
|
||||
"terminal": "Terminal Access",
|
||||
"terminalSummary": "Direct access to each container's and server terminal for advanced management.",
|
||||
"terminalDes": "Provides an interface to access the command line of any active container, allowing developers to execute commands, manage services, and troubleshoot directly from the dashboard"
|
||||
},
|
||||
"callToAction": {
|
||||
"title": "Unlock Your Deployment Potential",
|
||||
"des": "Streamline your deployments with our PaaS. Effortlessly manage Docker containers and traffic with Traefik. Boost your infrastructure's efficiency and security today",
|
||||
"button": "Get Started Now"
|
||||
},
|
||||
"faq": {
|
||||
"title": "Frequently asked questions",
|
||||
"des": "If you can’t find what you’re looking for, email our support team and if you’re lucky someone will get back to you.",
|
||||
"q1": "What is dokploy?",
|
||||
"a1": "Dokploy is a stable, easy-to-use deployment solution designed to simplify the application management process. Think of Dokploy as a free alternative self-hostable solution to platforms like Heroku, Vercel, and Netlify.",
|
||||
"q2": "Why Choose Dokploy?",
|
||||
"a2": "Simplicity, Flexibility, and Fast",
|
||||
"q3": "Is free?",
|
||||
"a3": "Yes, dokploy is totally free. You can use it for personal projects, small teams, or even for large-scale applications.",
|
||||
"q4": "Is it open source?",
|
||||
"a4": "Yes, dokploy is open source and free to use.",
|
||||
"q5": "What type of applications can i deploy with dokploy?",
|
||||
"a5": "Dokploy is a great choice for any type of application. You can deploy your code to dokploy and manage it from the dashboard. We support a wide range of languages and frameworks, so you can choose the one that best fits your needs.",
|
||||
"q6": "How do I request a feature or report a bug?",
|
||||
"a6": "Currently we are working on fixing bug fixes, but we will be releasing new features soon. You can also request features or report bugs.",
|
||||
"q7": "Do you track the usage of Dokploy?",
|
||||
"a7": "No, we don't track any usage data.",
|
||||
"q8": "Are there any user forums or communities where I can interact with other users?",
|
||||
"a8": "Yes, we have active github discussions where you can share ideas, ask for help, and connect with other users.",
|
||||
"q9": "What types of applications can I deploy with Dokploy?",
|
||||
"a9": "Dokploy supports a variety of applications, including those built with Docker, as well as applications from any Git repository, offering custom builds with Nixpacks, Dockerfiles, or Buildpacks like Heroku and Paketo.",
|
||||
"q10": "How does Dokploy handle database management?",
|
||||
"a10": "Dokploy supports multiple database systems including Postgres, MySQL, MariaDB, MongoDB, and Redis, providing tools for easy deployment and management directly from the dashboard."
|
||||
},
|
||||
"footer": {
|
||||
"copyright": "Copyright © {year} Dokploy. All rights reserved."
|
||||
}
|
||||
}
|
||||
}
|
||||
82
apps/website/locales/zh-Hans.json
Normal file
82
apps/website/locales/zh-Hans.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"HomePage": {
|
||||
"navigation": {
|
||||
"features": "特性",
|
||||
"faqs": "FAQ",
|
||||
"docs": "文档",
|
||||
"support": "赞助",
|
||||
"discord": "Discord"
|
||||
},
|
||||
"hero": {
|
||||
"deploy": "部署在",
|
||||
"anywhere": "任何设施之上",
|
||||
"with": "",
|
||||
"des": "以前所未有的简洁和高效提供一站式项目、数据的管理以及系统监控。",
|
||||
"featuredIn": "发布于"
|
||||
},
|
||||
"primaryFeatures": {
|
||||
"title": "全面掌控您的基础设施",
|
||||
"des": "Dokploy 不仅简化您的项目部署和数据管理流程,同时还提供完备的数据备份,一切只在弹指间。",
|
||||
"projects": "项目",
|
||||
"projectsDes": "您所有的项目和所需的一切信息都将归集一处。",
|
||||
"applications": "应用和数据库",
|
||||
"applicationsDes": "Dokploy 通过集中管理您的应用和数据库来提升安全性和效率,并大大简化了跨基础设施的访问和管理。",
|
||||
"compose": "Docker Compose",
|
||||
"composeDes": "Dokploy 提供对复杂应用和服务的原生 Docker Compose 支持。",
|
||||
"multinode": "多节点",
|
||||
"multinodeDes": "Dokploy 使用 Docker Swarm 来管理集群,可自动将应用扩容至多个节点。",
|
||||
"monitoring": "监控",
|
||||
"monitoringDes": "随时掌控你的系统性能和应用健康,确保服务无间断运行。",
|
||||
"backups": "备份",
|
||||
"backupsDes": "使用 Dokploy 的自动备份功能来保护您的数据,并在需要时极速还原。"
|
||||
},
|
||||
"secondaryFeatures": {
|
||||
"title": "先进的管理工具",
|
||||
"des": "借助业界优秀的开源工具,Dokploy 不仅可以为您的基础设施提供精准的控制、详尽的监测、一流的安全,还能确保无缝的体验和强悍的性能。",
|
||||
"templates": "开源模板",
|
||||
"templatesSummary": "一键部署热门开源项目",
|
||||
"templatesDes": "基于 Docker Compose 一键部署热门开源自建项目(Plausible 分析, Calcom 日历, Pocketbase, 等等.)",
|
||||
"traefik": "实时 Traefik 配置",
|
||||
"traefikSummary": "通过图形界面或API动态修改 Traefik 配置",
|
||||
"traefikDes": "用户可通过直观的界面或API调整Traefik的配置,包括中间件、转发规则及SSL证书。此功能使得流量路由和安全设置的调整无需重启服务即可无缝进行。",
|
||||
"users": "多用户权限管理",
|
||||
"usersSummary": "对用户访问和管理项目及服务的权限进行细致控制",
|
||||
"usersDes": "允许管理员为每个用户定义特定角色和权限,包括创建、修改或删除应用程序和数据库的能力。借助这一功能,Dokploy 为大型团队进行安全且高效的管理提供了有力支持。",
|
||||
"terminal": "终端访问",
|
||||
"terminalSummary": "从图形界面直接访问容器或者服务的终端",
|
||||
"terminalDes": "DokPloy 内置的界面可以帮助开发者直接访问容器终端并执行任何命令。 "
|
||||
},
|
||||
"callToAction": {
|
||||
"title": "释放自主部署的全部潜力",
|
||||
"des": "借助我们的 PaaS 软件来简化部署流程,使用 Traefik 轻松管理 Docker 容器和流量,立即提高基础设施的效率和安全性。",
|
||||
"button": "现在就部署"
|
||||
},
|
||||
"faq": {
|
||||
"title": "常问问题",
|
||||
"des": "如果您要寻找的问题不在下方,请通过我们的 GitHub 仓库提交 issue 或在我们的 Discord 提出问题。",
|
||||
"q1": "什么是 dokploy?",
|
||||
"a1": "Dokploy 是一个稳定易用的自部署解决方案,设计用于简化项目部署过程。您可以把 DokPloy 想象成一个自部署的 Vercel/Netlify/Heroku 平台。",
|
||||
"q2": "为什么选择 Dokploy?",
|
||||
"a2": "简洁, 灵活, 还有高效!",
|
||||
"q3": "真的免费?",
|
||||
"a3": "是的, dokploy 完全免费。不管是个人使用还是团队使用,都不收取费用。",
|
||||
"q4": "这是开源的吗?",
|
||||
"a4": "Dokploy 的所有代码皆可在我们的托管平台找到。",
|
||||
"q5": "Dokploy 可以支持部署什么编程语言的项目?",
|
||||
"a5": "Dokploy 对编程语言没有限制, 您可以部署任何您喜爱的语言或者框架。",
|
||||
"q6": "想提出新的功能需求或者遇到了问题?",
|
||||
"a6": "您可以前往我们的 Github 打开一个新的 issue,或者在我们的 GitHub讨论区 或 Discord 中发帖。",
|
||||
"q7": "Dokploy是否内置遥测?",
|
||||
"a7": "不,Dokploy不收集任何使用数据。",
|
||||
"q8": "有什么用户社群可以便于我和其他用户交流吗?",
|
||||
"a8": "您可以在我们的GitHub讨论区自由讨论,如果您愿意还可以加入我们的 Discord。",
|
||||
"q9": "dokploy 可以支持部署哪种类型的应用?",
|
||||
"a9": "Dokploy 支持很多应用,不仅包括 Docker 镜像,也可以从 Git Repository 直接启动,DokPloy 提供了丰富的自定义构建工具,如 Nixpacks, Dockerfiles, 抑或是 Buildpacks (就像 Heroku 和 Paketo)",
|
||||
"q10": "Dokploy 支持哪些数据库?",
|
||||
"a10": "Dokploy 支持 Postgres, MySQL, MariaDB, MongoDB, 以及 Redis。我们还提供方便的图形化管理工具以供使用。"
|
||||
},
|
||||
"footer": {
|
||||
"copyright": "版权属于 © {year} Dokploy, 保留所有权利"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user