refactor: remove internationalization middleware and related localization files; update layout and components to use new translation utility

This commit is contained in:
Mauricio Siu
2025-11-05 01:11:41 -06:00
parent d0c5bf91ab
commit b51c6a8f58
23 changed files with 115 additions and 1104 deletions

View File

@@ -1,88 +0,0 @@
import { Inter, Lexend } from "next/font/google";
import "@/styles/tailwind.css";
import "react-photo-view/dist/react-photo-view.css";
import { Footer } from "@/components/Footer";
import { Header } from "@/components/Header";
import type { Metadata } from "next";
import { setRequestLocale } from "next-intl/server";
export const metadata: Metadata = {
metadataBase: new URL("https://dokploy.com"),
title: {
default: "Dokploy - Effortless Deployment Solutions",
template: "%s | Simplify Your DevOps",
},
icons: {
icon: "icon.svg",
apple: "apple-touch-icon.png",
},
alternates: {
canonical: "https://dokploy.com",
languages: {
en: "https://dokploy.com",
},
},
description:
"Streamline your deployment process with Dokploy. Effortlessly manage applications and databases on any VPS using Docker and Traefik for improved performance and security.",
applicationName: "Dokploy",
keywords: [
"Dokploy",
"Docker",
"Traefik",
"deployment",
"VPS",
"application management",
"database management",
"DevOps",
"cloud infrastructure",
"UI Self hosted",
],
referrer: "origin",
robots: "index, follow",
openGraph: {
type: "website",
url: "https://dokploy.com",
title: "Dokploy - Effortless Deployment Solutions",
description:
"Simplify your DevOps with Dokploy. Deploy applications and manage databases efficiently on any VPS.",
siteName: "Dokploy",
images: [
{
url: "https://dokploy.com/og.png",
},
{
url: "https://dokploy.com/icon.svg",
width: 24,
height: 24,
alt: "Dokploy Logo",
},
],
},
twitter: {
card: "summary_large_image",
site: "@Dokploy",
creator: "@Dokploy",
title: "Dokploy - Simplify Your DevOps",
description:
"Deploy applications and manage databases with ease using Dokploy. Learn how our platform can elevate your infrastructure management.",
images: "https://dokploy.com/og.png",
},
};
export default async function RootLayout({
children,
params,
}: {
children: React.ReactNode;
params: { locale: string };
}) {
const { locale } = await params;
setRequestLocale(locale);
return (
<div className="flex h-full flex-col">
<Header />
{children}
<Footer />
</div>
);
}

View File

@@ -1,7 +1,6 @@
"use client";
import { useState } from "react";
import { useTranslations } from "next-intl";
import { Container } from "@/components/Container";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@@ -26,7 +25,6 @@ interface ContactFormData {
}
export default function ContactPage() {
const t = useTranslations("Contact");
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const [formData, setFormData] = useState<ContactFormData>({
@@ -43,24 +41,24 @@ export default function ContactPage() {
const newErrors: Record<string, string> = {};
if (!formData.inquiryType) {
newErrors.inquiryType = t("errors.inquiryTypeRequired");
newErrors.inquiryType = "Please select what we can help you with";
}
if (!formData.firstName.trim()) {
newErrors.firstName = t("errors.firstNameRequired");
newErrors.firstName = "First name is required";
}
if (!formData.lastName.trim()) {
newErrors.lastName = t("errors.lastNameRequired");
newErrors.lastName = "Last name is required";
}
if (!formData.email.trim()) {
newErrors.email = t("errors.emailRequired");
newErrors.email = "Email is required";
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
newErrors.email = t("errors.emailInvalid");
newErrors.email = "Please enter a valid email address";
}
if (!formData.company.trim()) {
newErrors.company = t("errors.companyRequired");
newErrors.company = "Company name is required";
}
if (!formData.message.trim()) {
newErrors.message = t("errors.messageRequired");
newErrors.message = "Message is required";
}
setErrors(newErrors);
@@ -86,14 +84,12 @@ export default function ContactPage() {
});
if (response.ok) {
// Track successful form submission
trackGAEvent({
action: "Contact Form Submitted",
category: "Contact",
label: formData.inquiryType,
});
// Reset form and show success
setFormData({
inquiryType: "",
firstName: "",
@@ -109,7 +105,7 @@ export default function ContactPage() {
}
} catch (error) {
console.error("Error submitting form:", error);
alert(t("errorMessage"));
alert("There was an error sending your message. Please try again.");
} finally {
setIsSubmitting(false);
}
@@ -117,7 +113,6 @@ export default function ContactPage() {
const handleInputChange = (field: keyof ContactFormData, value: any) => {
setFormData((prev) => ({ ...prev, [field]: value }));
// Clear error when user starts typing
if (errors[field]) {
setErrors((prev) => {
const newErrors = { ...prev };
@@ -133,14 +128,15 @@ export default function ContactPage() {
<Container>
<div className="mx-auto max-w-2xl text-center">
<h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
{t("successTitle")}
Thank you for contacting us!
</h1>
<p className="mt-6 text-lg leading-8 text-muted-foreground">
{t("successMessage")}
We've received your message and will get back to you as soon as
possible.
</p>
<div className="mt-10">
<Button onClick={() => setIsSubmitted(false)} variant="outline">
{t("buttons.sendAnother")}
Send Another Message
</Button>
</div>
</div>
@@ -167,10 +163,11 @@ export default function ContactPage() {
<div className="mx-auto max-w-3xl border border-border rounded-lg p-8 bg-black z-10 relative">
<div className="text-center">
<h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
{t("title")}
Contact Us
</h1>
<p className="mt-6 text-lg leading-8 text-muted-foreground">
{t("description")}
Get in touch with our team. We're here to help with any questions
about Dokploy.
</p>
</div>
@@ -180,7 +177,7 @@ export default function ContactPage() {
htmlFor="inquiryType"
className="block text-sm font-medium text-foreground"
>
{t("fields.inquiryType.label")}{" "}
What can we help you with today?{" "}
<span className="text-red-500">*</span>
</label>
<Select
@@ -193,20 +190,12 @@ export default function ContactPage() {
}
>
<SelectTrigger className="bg-input">
<SelectValue
placeholder={t("fields.inquiryType.placeholder")}
/>
<SelectValue placeholder="Select an option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="support">
{t("fields.inquiryType.options.support")}
</SelectItem>
<SelectItem value="sales">
{t("fields.inquiryType.options.sales")}
</SelectItem>
<SelectItem value="other">
{t("fields.inquiryType.options.other")}
</SelectItem>
<SelectItem value="support">Support</SelectItem>
<SelectItem value="sales">Sales</SelectItem>
<SelectItem value="other">Other</SelectItem>
</SelectContent>
</Select>
{errors.inquiryType && (
@@ -220,8 +209,7 @@ export default function ContactPage() {
htmlFor="firstName"
className="block text-sm font-medium text-foreground"
>
{t("fields.firstName.label")}{" "}
<span className="text-red-500">*</span>
First Name <span className="text-red-500">*</span>
</label>
<Input
id="firstName"
@@ -230,7 +218,7 @@ export default function ContactPage() {
onChange={(e) =>
handleInputChange("firstName", e.target.value)
}
placeholder={t("fields.firstName.placeholder")}
placeholder="Your first name"
/>
{errors.firstName && (
<p className="text-sm text-red-600">{errors.firstName}</p>
@@ -242,8 +230,7 @@ export default function ContactPage() {
htmlFor="lastName"
className="block text-sm font-medium text-foreground"
>
{t("fields.lastName.label")}{" "}
<span className="text-red-500">*</span>
Last Name <span className="text-red-500">*</span>
</label>
<Input
id="lastName"
@@ -252,7 +239,7 @@ export default function ContactPage() {
onChange={(e) =>
handleInputChange("lastName", e.target.value)
}
placeholder={t("fields.lastName.placeholder")}
placeholder="Your last name"
/>
{errors.lastName && (
<p className="text-sm text-red-600">{errors.lastName}</p>
@@ -265,15 +252,14 @@ export default function ContactPage() {
htmlFor="email"
className="block text-sm font-medium text-foreground"
>
{t("fields.email.label")}{" "}
<span className="text-red-500">*</span>
Email <span className="text-red-500">*</span>
</label>
<Input
id="email"
type="email"
value={formData.email}
onChange={(e) => handleInputChange("email", e.target.value)}
placeholder={t("fields.email.placeholder")}
placeholder="your.email@company.com"
/>
{errors.email && (
<p className="text-sm text-red-600">{errors.email}</p>
@@ -285,15 +271,14 @@ export default function ContactPage() {
htmlFor="company"
className="block text-sm font-medium text-foreground"
>
{t("fields.company.label")}{" "}
<span className="text-red-500">*</span>
Company Name <span className="text-red-500">*</span>
</label>
<Input
id="company"
type="text"
value={formData.company}
onChange={(e) => handleInputChange("company", e.target.value)}
placeholder={t("fields.company.placeholder")}
placeholder="Your company name"
/>
{errors.company && (
<p className="text-sm text-red-600">{errors.company}</p>
@@ -305,14 +290,13 @@ export default function ContactPage() {
htmlFor="message"
className="block text-sm font-medium text-foreground"
>
{t("fields.message.label")}{" "}
<span className="text-red-500">*</span>
How can we help? <span className="text-red-500">*</span>
</label>
<textarea
id="message"
value={formData.message}
onChange={(e) => handleInputChange("message", e.target.value)}
placeholder={t("fields.message.placeholder")}
placeholder="Tell us more about your inquiry..."
rows={6}
className="flex w-full rounded-md bg-input border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 resize-none"
/>
@@ -327,7 +311,7 @@ export default function ContactPage() {
disabled={isSubmitting}
className="min-w-[120px]"
>
{isSubmitting ? t("buttons.sending") : t("buttons.send")}
{isSubmitting ? "Sending..." : "Send Message"}
</Button>
</div>
</form>

View File

@@ -1,10 +1,12 @@
import clsx from "clsx";
import type { Metadata } from "next";
import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
import { Inter, Lexend } from "next/font/google";
import type { ReactNode } from "react";
import { GoogleAnalytics } from "@next/third-parties/google";
import "@/styles/tailwind.css";
import "react-photo-view/dist/react-photo-view.css";
import { Header } from "@/components/Header";
import { Footer } from "@/components/Footer";
type Props = {
children: ReactNode;
@@ -44,18 +46,10 @@ const lexend = Lexend({
});
// Since we have a `not-found.tsx` page on the root, a layout file
// is required, even if it's just passing children through.
export default async function RootLayout({
children,
params,
}: {
children: ReactNode;
params: { locale: string };
}) {
const { locale } = params;
const messages = await getMessages();
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html
lang={locale}
lang="en"
className={clsx(
"h-full scroll-smooth antialiased",
inter.variable,
@@ -73,9 +67,11 @@ export default async function RootLayout({
</head>
<body>
<GoogleAnalytics gaId="G-0RTZ5EPB26" />
<NextIntlClientProvider messages={messages}>
<div className="flex h-full flex-col">
<Header />
{children}
</NextIntlClientProvider>
<Footer />
</div>
</body>
</html>
);

View File

@@ -7,11 +7,8 @@ import { Pricing } from "@/components/pricing";
import { SecondaryFeaturesSections } from "@/components/secondary-features";
import { Sponsors } from "@/components/sponsors";
import { StatsSection } from "@/components/stats";
import { setRequestLocale } from "next-intl/server";
export default async function Home({ params }: { params: { locale: string } }) {
const { locale } = await params;
setRequestLocale(locale);
export default function Home() {
return (
<div>
<main>

View File

@@ -1,5 +1,5 @@
import { Container } from "@/components/Container";
import { useTranslations } from "next-intl";
import { useTranslations } from "@/lib/intl";
import Link from "next/link";
import { Button } from "./ui/button";

View File

@@ -4,7 +4,7 @@ import {
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { useTranslations } from "next-intl";
import { useTranslations } from "@/lib/intl";
import { Container } from "./Container";
const faqs = [

View File

@@ -1,13 +1,6 @@
"use client";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
} from "@/components/ui/select";
import { Link, useRouter } from "@/i18n/routing";
import { useLocale, useTranslations } from "next-intl";
import Link from "next/link";
import type { SVGProps } from "react";
import { Container } from "./Container";
import { NavLink } from "./NavLink";
@@ -33,11 +26,6 @@ const I18nIcon = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
);
export function Footer() {
const router = useRouter();
const locale = useLocale();
const t = useTranslations("HomePage");
const linkT = useTranslations("Link");
return (
<footer className="bg-black">
<Container>
@@ -51,10 +39,13 @@ export function Footer() {
<nav className="mt-10 text-sm" aria-label="quick links">
<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={linkT("docs.intro")} target="_blank">
{t("navigation.docs")}
<NavLink href="/#features">Features</NavLink>
<NavLink href="/#faqs">FAQ</NavLink>
<NavLink
href="https://docs.dokploy.com/docs/core"
target="_blank"
>
Docs
</NavLink>
</div>
</nav>
@@ -89,39 +80,9 @@ export function Footer() {
<path d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0 1 12 6.844a9.59 9.59 0 0 1 2.504.337c1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.02 10.02 0 0 0 22 12.017C22 6.484 17.522 2 12 2Z" />
</svg>
</Link>
<Select
onValueChange={(locale) => {
router.replace("/", {
locale: locale as "en" | "zh-Hans" | "fr" | "es",
});
router.refresh();
}}
value={locale}
>
<SelectTrigger
className={buttonVariants({
variant: "outline",
className:
" flex items-center gap-2 !rounded-full visited:outline-none focus-within:outline-none focus:outline-none",
})}
>
<I18nIcon width={20} height={20} />
</SelectTrigger>
<SelectContent>
<SelectItem value="en">{t("navigation.i18nEn")}</SelectItem>
<SelectItem value="fr">{t("navigation.i18nFr")}</SelectItem>
<SelectItem value="es">{t("navigation.i18nEs")}</SelectItem>
<SelectItem value="zh-Hans">
{t("navigation.i18nZh-Hans")}
</SelectItem>
</SelectContent>
</Select>
</div>
<p className="mt-6 text-sm text-muted-foreground sm:mt-0">
{t("footer.copyright", {
year: new Date().getFullYear(),
})}
{`Copyright © ${new Date().getFullYear()} Dokploy. All rights reserved.`}
</p>
</div>
</Container>

View File

@@ -1,10 +1,9 @@
"use client";
import { Link } from "@/i18n/routing";
import Link from "next/link";
import { cn } from "@/lib/utils";
import { Popover, Transition } from "@headlessui/react";
import { ChevronRight, HeartIcon } from "lucide-react";
import { useTranslations } from "next-intl";
import { Fragment, type JSX, type SVGProps } from "react";
import { Container } from "./Container";
import { NavLink } from "./NavLink";
@@ -84,8 +83,6 @@ const I18nIcon = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
);
function MobileNavigation() {
const t = useTranslations("HomePage");
const linkT = useTranslations("Link");
return (
<Popover>
<Popover.Button
@@ -120,16 +117,20 @@ function MobileNavigation() {
as="div"
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="/#pricing">
{t("navigation.pricing")}
<MobileNavLink href="/#pricing">Pricing</MobileNavLink>
<MobileNavLink href="/#faqs">FAQ</MobileNavLink>
<MobileNavLink
href="https://docs.dokploy.com/docs/core"
target="_blank"
>
Docs
</MobileNavLink>
<MobileNavLink href="/#faqs">{t("navigation.faqs")}</MobileNavLink>
<MobileNavLink href={linkT("docs.intro")} target="_blank">
{t("navigation.docs")}
</MobileNavLink>
<MobileNavLink href="/blog">{t("navigation.blog")}</MobileNavLink>
<MobileNavLink href="/contact">{t("navigation.contact")}</MobileNavLink>
<MobileNavLink href={linkT("docs.intro")} target="_blank">
<MobileNavLink href="/blog">Blog</MobileNavLink>
<MobileNavLink href="/contact">Contact</MobileNavLink>
<MobileNavLink
href="https://docs.dokploy.com/docs/core"
target="_blank"
>
<Button className=" w-full" asChild>
<Link
href="https://app.dokploy.com/register"
@@ -137,7 +138,7 @@ function MobileNavigation() {
target="_blank"
>
<div className="group flex-row relative mx-auto flex max-w-fit items-center justify-center rounded-2xl text-sm font-medium w-full">
<span>{t("navigation.dashboard")}</span>
<span>Sign In</span>
<ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
</div>
</Link>
@@ -151,9 +152,6 @@ function MobileNavigation() {
}
export function Header() {
const t = useTranslations("HomePage");
const linkT = useTranslations("Link");
return (
<header className="bg-background py-10">
<Container>
@@ -163,12 +161,15 @@ export function Header() {
<Logo className="h-10 w-auto" />
</Link>
<div className="hidden md:flex md:gap-x-6">
<NavLink href="/#pricing">{t("navigation.pricing")}</NavLink>
<NavLink href="/#faqs">{t("navigation.faqs")}</NavLink>
<NavLink href={linkT("docs.intro")} target="_blank">
{t("navigation.docs")}
<NavLink href="/#pricing">Pricing</NavLink>
<NavLink href="/#faqs">FAQ</NavLink>
<NavLink
href="https://docs.dokploy.com/docs/core"
target="_blank"
>
Docs
</NavLink>
<NavLink href="/blog">{t("navigation.blog")}</NavLink>
<NavLink href="/blog">Blog</NavLink>
</div>
</div>
<div className="flex items-center gap-x-4 md:gap-x-5">
@@ -200,7 +201,7 @@ export function Header() {
});
}}
>
{t("navigation.contact")}
Contact
</Link>
</Button>
@@ -225,7 +226,7 @@ export function Header() {
target="_blank"
>
<div className="group flex-row relative mx-auto flex max-w-fit items-center justify-center rounded-2xl text-sm font-medium w-full">
<span>{t("navigation.dashboard")}</span>
<span>Sign In</span>
<ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
</div>
</Link>

View File

@@ -2,7 +2,7 @@
import { cn } from "@/lib/utils";
import { motion } from "framer-motion";
import { Check, ChevronRight, Copy } from "lucide-react";
import { useTranslations } from "next-intl";
import { useTranslations } from "@/lib/intl";
import Link from "next/link";
import { useEffect, useState } from "react";
import AnimatedGradientText from "./ui/animated-gradient-text";

View File

@@ -1,6 +1,6 @@
"use client";
import { Link } from "@/i18n/routing";
import Link from "next/link";
import { trackGAEvent } from "./analitycs";
export function NavLink({

View File

@@ -4,7 +4,7 @@ import { cn } from "@/lib/utils";
import { Tab } from "@headlessui/react";
import { motion } from "framer-motion";
import { Layers, Terminal, Users } from "lucide-react";
import { useTranslations } from "next-intl";
import { useTranslations } from "@/lib/intl";
import { Container } from "./Container";
interface Feature {
name: React.ReactNode;

View File

@@ -1,4 +1,4 @@
import { Link } from "@/i18n/routing";
import Link from "next/link";
export function SlimLayout() {
return (

View File

@@ -11,7 +11,7 @@ import {
X,
XCircleIcon,
} from "lucide-react";
import { useTranslations } from "next-intl";
import { useTranslations } from "@/lib/intl";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";

View File

@@ -5,7 +5,7 @@ import { AnimatePresence, motion } from "framer-motion";
import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
import { useTranslations } from "next-intl";
import { useTranslations } from "@/lib/intl";
const features = [
{

View File

@@ -1,6 +1,6 @@
"use client";
import { PlusCircleIcon } from "lucide-react";
import { useTranslations } from "next-intl";
import { useTranslations } from "@/lib/intl";
import Link from "next/link";
import { buttonVariants } from "./ui/button";
import Ripple from "./ui/ripple";

View File

@@ -1,15 +0,0 @@
import { getRequestConfig } from "next-intl/server";
import { routing } from "./routing";
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale;
// Validate that the incoming `locale` parameter is valid
if (!locale || !routing.locales.includes(locale as any)) {
locale = routing.defaultLocale;
}
return {
locale,
messages: (await import(`../locales/${locale}.json`)).default,
};
});

View File

@@ -1,16 +0,0 @@
import { createSharedPathnamesNavigation } from "next-intl/navigation";
import { defineRouting } from "next-intl/routing";
export const routing = defineRouting({
// A list of all locales that are supported
locales: ["en", "fr", "es", "zh-Hans"],
// Used when no locale matches
defaultLocale: "en",
localePrefix: "as-needed",
});
// Lightweight wrappers around Next.js' navigation APIs
// that will consider the routing configuration
export const { Link, redirect, usePathname, useRouter } =
createSharedPathnamesNavigation(routing);

22
apps/website/lib/intl.ts Normal file
View File

@@ -0,0 +1,22 @@
import en from "../locales/en.json";
type Messages = typeof en;
function getByPath(obj: any, path: string): any {
return path
.split(".")
.reduce((acc, key) => (acc ? acc[key] : undefined), obj);
}
export function useTranslations(namespace?: keyof Messages | string) {
return (key: string, params?: Record<string, any>) => {
const fullKey = namespace ? `${namespace}.${key}` : key;
let value = getByPath(en as any, fullKey);
if (typeof value === "string" && params) {
for (const [k, v] of Object.entries(params)) {
value = value.replaceAll(`{${k}}`, String(v));
}
}
return value ?? fullKey;
};
}

View File

@@ -1,272 +0,0 @@
{
"HomePage": {
"navigation": {
"features": "Características",
"faqs": "Preguntas frecuentes",
"docs": "Documentación",
"pricing": "Precios",
"support": "Soporte",
"dashboard": "Acceder",
"discord": "Discord",
"i18nButtonPlaceholder": "Lenguaje",
"i18nFr": "Français",
"i18nEn": "English",
"i18nEs": "Español",
"i18nZh-Hans": "简体中文",
"blog": "Blog",
"home": "Inicio",
"login": "Iniciar sesión",
"register": "Registro",
"contact": "Contacto"
},
"hero": {
"cloud": "Introduciendo Dokploy Cloud",
"deploy": "Despliegue",
"anywhere": "en Cualquier lugar",
"with": "con Total Libertad y Facilidad.",
"des": "Simplifique sus operaciones con nuestra plataforma en un solo lugar — perfecta para gestionar proyectos, datos y salud del sistema con simplicidad y eficiencia.",
"featuredIn": "Destacado en",
"sponsors": {
"title": "Patrocinadores",
"description": "Dokploy es un proyecto de código abierto que es mantenido por una comunidad de voluntarios. Gracias a nuestros patrocinadores por su apoyo y contribuciones al proyecto, esto nos ayuda a continuar desarrollando y mejorando Dokploy.",
"level": {
"hero": "Patrocinadores Hero",
"premium": "Patrocinadores Premium",
"supporting": "Miembros de Apoyo",
"community": "Comunidad",
"organizations": "Organizaciones",
"individuals": "Individuos"
}
}
},
"primaryFeatures": {
"title": "Control integral para tu ecosistema digital.",
"des": "Simplifica la gestión de tus proyectos y datos, garantiza una supervisión robusta y asegura tus copias de seguridad, todo sin complicaciones ni preocuparte por los mínimos detalles.",
"projects": "Proyectos",
"templates": "Plantillas",
"templatesDes": "En un solo clic puedes desplegar plantillas de código abierto.",
"logs": "Registros",
"logsDes": "Supervisa y gestiona los registros de tus aplicaciones con facilidad, garantizando una resolución de problemas eficiente y un rendimiento óptimo.",
"projectsDes": "Gestiona y organiza todos tus proyectos en un solo lugar, manteniendo un seguimiento detallado del progreso y la asignación de recursos.",
"applications": "Aplicaciones & Bases de datos",
"applicationsDes": "Centraliza el control de tus aplicaciones y bases de datos para mejorar la seguridad y la eficiencia, simplificando el acceso y la gestión en toda tu infraestructura.",
"compose": "Docker Compose",
"composeDes": "Centraliza el control de tus aplicaciones y bases de datos para mejorar la seguridad y la eficiencia, simplificando el acceso y la gestión en toda tu infraestructura.",
"multiserver": "Multiservidor",
"multiserverDes": "Despliega aplicaciones en múltiples servidores sin esfuerzo.",
"monitoring": "Supervisión",
"monitoringDes": "Supervisa el rendimiento y la salud de tus sistemas en tiempo real, garantizando una operación continua e ininterrumpida.",
"backups": "Copias de seguridad",
"backupsDes": "Implementa soluciones de copia de seguridad automáticas y seguras para proteger tus datos críticos y restaurarlos rápidamente cuando sea necesario.",
"traefik": "Traefik",
"traefikDes": "Gestiona Traefik mediante el Editor de Archivos para configurar tus propios nombres de dominio, certificados y mucho más."
},
"secondaryFeatures": {
"title": "Herramientas de Gestión Avanzadas",
"des": "Eleva tu infraestructura con herramientas que ofrecen control preciso, supervisión detallada y mayor seguridad, garantizando una gestión fluida y un rendimiento sólido.",
"templates": "Plantillas de Código Abierto",
"templatesSummary": "En un solo clic puedes desplegar plantillas de código abierto.",
"templatesDes": "Despliega plantillas de código abierto con un solo clic, impulsadas por Docker Compose (Plausible, Calcom, Pocketbase, etc.).",
"traefik": "Configuración de Traefik en Tiempo Real",
"traefikSummary": "Modifica la configuración de Traefik al instante mediante una interfaz gráfica o una API.",
"traefikDes": "Los usuarios pueden ajustar la configuración de Traefik, incluyendo middleware, reglas de reenvío y certificados SSL, a través de una interfaz intuitiva o una API. Esta funcionalidad permite realizar ajustes en el enrutamiento del tráfico y la seguridad sin necesidad de reiniciar los servicios.",
"users": "Gestión de Permisos de Usuario",
"usersSummary": "Control detallado sobre los permisos de usuario para acceder y gestionar proyectos y servicios.",
"usersDes": "Permite a los administradores definir roles y permisos específicos para cada usuario, incluyendo la capacidad de crear, modificar o eliminar aplicaciones y bases de datos. Esta funcionalidad garantiza una gestión segura y eficiente de equipos grandes y diversos.",
"terminal": "Acceso a la Terminal",
"terminalSummary": "Acceso directo a la terminal de cada contenedor y servidor para una gestión avanzada.",
"terminalDes": "Proporciona una interfaz para acceder a la línea de comandos de cualquier contenedor activo, permitiendo a los desarrolladores ejecutar comandos, gestionar servicios y solucionar problemas directamente desde el panel de control."
},
"callToAction": {
"title": "Desbloquea tu potencial de despliegue con Dokploy Cloud.",
"des": "Despídete de las complicaciones de infraestructura—Dokploy Cloud lo gestiona todo. Despliega y gestiona contenedores Docker sin esfuerzo y asegura tu tráfico con Traefik. Tú céntrate en construir, nosotros nos encargamos del resto.",
"button": "Comenzar Ahora"
},
"faq": {
"title": "Preguntas frecuentes",
"des": "Si no encuentras lo que estás buscando, por favor envía un problema a través de nuestro repositorio de GitHub o haz tus preguntas en nuestro Discord.",
"q1": "¿Qué es Dokploy?",
"a1": "Dokploy es una solución de despliegue estable y fácil de usar, diseñada para simplificar el proceso de gestión de aplicaciones. Piensa en Dokploy como una alternativa gratuita y autohospedable a plataformas como Heroku, Vercel y Netlify.",
"q2": "¿Por qué usar Dokploy?",
"a2": "Dokploy ofrece simplicidad, flexibilidad y rapidez en el despliegue y la gestión de aplicaciones.",
"q4": "¿Dokploy es de código abierto?",
"a4": "Sí, Dokploy es de código abierto y gratuito.",
"q5": "¿Qué tipos de lenguajes puedo desplegar con Dokploy?",
"a5": "Dokploy no restringe lenguajes de programación. Puedes elegir el lenguaje y el framework que prefieras.",
"q6": "¿Cómo puedo solicitar una característica o reportar un error?",
"a6": "Para solicitar una característica o reportar un error, por favor crea un problema en nuestro repositorio de GitHub o haz preguntas en nuestro Discord.",
"q7": "¿Se rastrea el uso de Dokploy?",
"a7": "No, no rastreamos ningún dato de uso.",
"q8": "¿Hay foros o comunidades donde pueda interactuar con otros usuarios?",
"a8": "Sí, tenemos discusiones activas en GitHub y Discord donde puedes compartir ideas, solicitar ayuda y conectarte con otros usuarios.",
"q9": "¿Qué tipos de aplicaciones puedo desplegar con Dokploy?",
"a9": "Puedes desplegar cualquier aplicación que pueda ser Dockerizada, sin limites. Dokploy soporta builds desde repositorios Git, Dockerfiles, Nixpacks y Buildpacks como Heroku y Paketo.",
"q10": "¿Cómo gestiona Dokploy el manejo de bases de datos?",
"a10": "Dokploy soporta múltiples sistemas de base de datos, incluyendo Postgres, MySQL, MariaDB, MongoDB y Redis, proporcionando herramientas para despliegue, gestión y copias de seguridad directamente desde el panel de control.",
"q11": "¿Cómo funciona el plan de código abierto de Dokploy?",
"a11": "Puedes hospedar la UI de Dokploy en tu propia infraestructura, tu serás responsable del mantenimiento y las actualizaciones.",
"q12": "¿Necesito proporcionar mi propio servidor para el plan gestionado?",
"a12": "Sí, en el plan gestionado, proporcionas tu propio servidor, por ejemplo: (Hetzner, Hostinger, AWS, ETC.) VPS, y gestionamos la infraestructura de la UI de Dokploy para ti.",
"q13": "¿Qué sucede si necesito más de un servidor?",
"a13": "El primer servidor cuesta $4.50/mes, si compras más de uno, será $3.50/mes por servidor.",
"q14": "¿Hay un límite en el número de despliegues?",
"a14": "No, no hay límite en el número de despliegues en ningún plan.",
"q15": "¿Qué sucede si excedo el límite de servidor comprado?",
"a15": "Los servidores recientemente agregados se desactivarán. No podrás crear servicios en servidores inactivos hasta que se reactiven.",
"q16": "¿Ofrecen reembolsos?",
"a16": "No, no ofrecemos reembolsos. Sin embargo, puedes cancelar tu suscripción en cualquier momento. ¡Sienteté libre de probar nuestra versión de código abierto antes de hacer un pedido!",
"q17": "¿Qué tipo de soporte ofrecéis?",
"a17": "Ofrecemos soporte comunitario para la versión de código abierto y soporte de prioridad para los planes de pago (a través de Discord o Email a support@dokploy.com).",
"q18": "¿Qué sucede con el plan de pago?",
"a18": "Nada, solo vinculas tu servidor(VPS) a tu cuenta y puedes desplegar aplicaciones, bases de datos y usuarios ilimitados y obtienes actualizaciones, despliegues, copias de seguridad y más."
},
"footer": {
"copyright": "Copyright © {year} Dokploy. Todos los derechos reservados."
}
},
"404": {
"title": "Oops! Parece que te has perdido.",
"des": "Vamos a ponerte de nuevo en el camino",
"action": "home"
},
"Link": {
"docs": {
"intro": "https://docs.dokploy.com/docs/core",
"install": "https://docs.dokploy.com/docs/core/installation"
}
},
"Pricing": {
"swirlyDoodleTitle": "Simple & Asequible,",
"restTitle": "Precios.",
"description": "Despliegue Inteligente, Escalado Rápido Sin Arruinarse",
"billingCycle": {
"monthly": "Mensual",
"annual": "Anual"
},
"plan": {
"free": {
"title": "Gratis",
"subTitle": "Código Abierto",
"section": {
"title": "Dokploy es de Código Abierto",
"description": "Gestiona tu propia infraestructura, instalando Dokploy UI en tu propio servidor."
},
"features": {
"f1": "Flexibilidad Total: Instala Dokploy UI en tu propia infraestructura",
"f2": "Infraestructura autohospedada",
"f3": "Soporte comunitario",
"f4": "Acceso a características básicas",
"f5": "Acceso a todas las actualizaciones",
"f9": "Servidores ilimitados"
},
"go": "Instalación"
},
"cloud": {
"title": "Recomendado",
"section": {
"title": "Dokploy Plan",
"description": "Gestionamos la infraestructura de la UI de Dokploy por ti."
},
"servers": "{serverQuantity} Servidores (Tienes que proporcionar los servidores)",
"features": {
"f1": "Gestión de Hosting: No tienes que preocuparte por la gestión de los servidores",
"f2": "Despliegues ilimitados",
"f3": "Bases de datos ilimitadas",
"f4": "Aplicaciones ilimitadas",
"f5": "Usuarios ilimitados",
"f6": "Monitoreo de servidores remotos",
"f7": "Soporte prioritario",
"f8": "Nuevas actualizaciones"
},
"go": "Suscribirme"
}
},
"faq": {
"title": "Preguntas Frecuentes",
"description": "Si no encuentras lo que estás buscando, por favor envía un problema a través de nuestro repositorio de GitHub o haz preguntas en nuestro Discord.",
"q1": "¿Cómo funciona el plan de código abierto de Dokploy?",
"a1": "Puedes hospedar la UI de Dokploy en tu propia infraestructura, tu serás responsable del mantenimiento y las actualizaciones.",
"q2": "¿Necesito proporcionar mi propio servidor para el plan gestionado?",
"a2": "Sí, en el plan gestionado, proporcionas tu propio servidor, por ejemplo: (Hetzner, Hostinger, AWS, ETC.) VPS, y gestionamos la infraestructura de la UI de Dokploy para ti.",
"q3": "¿Qué sucede si necesito más de un servidor?",
"a3": "El primer servidor cuesta $4.50/mes, si compras más de uno, será $3.50/mes por servidor.",
"q4": "¿Hay un límite en el número de despliegues?",
"a4": "No, no hay límite en el número de despliegues en ningún plan.",
"q5": "¿Qué sucede si excedo el límite de servidor comprado?",
"a5": "Los servidores recientemente agregados se desactivarán. No podrás crear servicios en servidores inactivos hasta que se reactiven.",
"q6": "¿Ofrecen reembolsos?",
"a6": "No, no ofrecemos reembolsos. Sin embargo, puedes cancelar tu suscripción en cualquier momento. ¡Sienteté libre de probar nuestra versión de código abierto antes de hacer un pedido!",
"q7": "¿Qué tipo de soporte ofrecéis?",
"a7": "Ofrecemos soporte comunitario para la versión de código abierto y soporte de prioridad para los planes de pago (a través de Discord o Email a support@dokploy.com).",
"q8": "¿Qué sucede con el plan de pago?",
"a8": "Nada, solo vinculas tu servidor(VPS) a tu cuenta y puedes desplegar aplicaciones, bases de datos y usuarios ilimitados y obtienes actualizaciones, despliegues, copias de seguridad y más."
}
},
"blog": {
"title": "Blog",
"description": "Noticias, actualizaciones y artículos de Dokploy",
"noPosts": "No hay publicaciones disponibles",
"noResults": "No se encontraron publicaciones que coincidan con tus criterios",
"searchPlaceholder": "Buscar publicaciones...",
"allTags": "Todas las etiquetas",
"relatedPosts": "Publicaciones Relacionadas",
"tagDescription": "Publicaciones etiquetadas con",
"foundPosts": "{count, plural, =0 {No posts found} one {# post found} other {# posts found}}",
"tagTitle": "Publicaciones etiquetadas con {tag}",
"backToBlog": "Volver al Blog",
"tags": "Etiquetas",
"postsTaggedWith": "Publicaciones etiquetadas con"
},
"Contact": {
"title": "Contáctanos",
"description": "Ponte en contacto con nuestro equipo. Estamos aquí para ayudarte con cualquier pregunta sobre Dokploy.",
"successTitle": "¡Gracias por contactarnos!",
"successMessage": "Hemos recibido tu mensaje y te responderemos lo antes posible.",
"errorMessage": "Hubo un error al enviar tu mensaje. Por favor, inténtalo de nuevo.",
"fields": {
"inquiryType": {
"label": "¿En qué podemos ayudarte hoy?",
"placeholder": "Selecciona una opción",
"options": {
"support": "Soporte",
"sales": "Ventas",
"other": "Otro"
}
},
"firstName": {
"label": "Nombre",
"placeholder": "Tu nombre"
},
"lastName": {
"label": "Apellido",
"placeholder": "Tu apellido"
},
"email": {
"label": "Correo electrónico",
"placeholder": "tu.email@empresa.com"
},
"company": {
"label": "Nombre de la empresa",
"placeholder": "El nombre de tu empresa"
},
"message": {
"label": "¿Cómo podemos ayudarte?",
"placeholder": "Cuéntanos más sobre tu consulta..."
}
},
"buttons": {
"send": "Enviar mensaje",
"sending": "Enviando...",
"sendAnother": "Enviar otro mensaje"
},
"errors": {
"inquiryTypeRequired": "Por favor selecciona en qué podemos ayudarte",
"firstNameRequired": "El nombre es obligatorio",
"lastNameRequired": "El apellido es obligatorio",
"emailRequired": "El correo electrónico es obligatorio",
"emailInvalid": "Por favor ingresa un correo electrónico válido",
"companyRequired": "El nombre de la empresa es obligatorio",
"messageRequired": "El mensaje es obligatorio"
}
}
}

View File

@@ -1,266 +0,0 @@
{
"HomePage": {
"navigation": {
"features": "Fonctionnalités",
"faqs": "Questions",
"docs": "Documentation",
"pricing": "Tarifs",
"support": "Support",
"dashboard": "S'inscrire",
"discord": "Discord",
"i18nButtonPlaceholder": "Langue",
"i18nFr": "Français",
"i18nEn": "English",
"i18nEs": "Español",
"i18nZh-Hans": "简体中文",
"blog": "Blog",
"home": "Accueil",
"login": "Connexion",
"register": "S'inscrire",
"contact": "Contact"
},
"hero": {
"cloud": "Présentation de Dokploy Cloud",
"deploy": "Deployer",
"anywhere": "N'importe où",
"with": "en toute liberté et facilement.",
"des": "Optimisez vos opérations grâce à notre plateforme tout-en-un : idéale pour gérer vos projets, données et l'état de vos systèmes avec simplicité et efficacité.",
"featuredIn": "En vedette sur",
"sponsors": {
"title": "Partenaires",
"description": "Dokploy est un projet open source qui est maintenu par une communauté de volontaires. Nous voudrions remercier nos partenaires pour leur soutien et leurs contributions au projet, qui nous aide à continuer à développer et à améliorer Dokploy.",
"level": {
"hero": "Partenaires spéciaux",
"premium": "Soutiens premium",
"supporting": "Membres soutenants",
"community": "Soutiens de la communauté",
"organizations": "Organisations",
"individuals": "Particuliers"
}
}
},
"primaryFeatures": {
"title": "Contrôle complet de votre écosystème numérique",
"des": "Simplifiez la gestion de vos projets et données, assurez une surveillance robuste et sécurisez vos sauvegardes — tout cela sans vous soucier des détails minutieux.",
"projects": "Projets",
"templates": "Templates",
"templatesDes": "Un clic pour déployer des templates open source.",
"logs": "Logs",
"logsDes": "Surveillez et gérez les logs de vos applications avec facilité, en assurant un dépannage efficace et des performances optimales.",
"projectsDes": "Gérez et organisez tous vos projets au même endroit, en suivant de manière détaillée l'avancement et l'allocation des ressources.",
"applications": "Applications & Bases de données",
"applicationsDes": "Centralisez le contrôle de vos applications et bases de données pour améliorer la sécurité et l'efficacité, simplifiant l'accès et la gestion sur toute votre infrastructure.",
"compose": "Docker Compose",
"composeDes": "Support natif de Docker Compose pour gérer des applications et services complexes avec facilité.",
"multiserver": "Multi Serveur",
"multiserverDes": "Déployez des applications sur plusieurs serveurs sans effort.",
"monitoring": "Surveillance",
"monitoringDes": "Surveillez les performances et la santé de vos systèmes en temps réel, garantissant une opération continue et ininterrompue.",
"backups": "Sauvegardes",
"backupsDes": "Mettez en place des solutions de sauvegarde automatiques et sécurisées pour protéger vos données critiques et les restaurer rapidement en cas de besoin.",
"traefik": "Traefik",
"traefikDes": "Gérez Traefik via l'éditeur de fichiers pour configurer vos propres noms de domaine, certificats, et plus encore."
},
"secondaryFeatures": {
"title": "Outils de gestion avancés",
"des": "Améliorez votre infrastructure avec des outils offrant un contrôle précis, une surveillance détaillée et une sécurité renforcée, garantissant une gestion fluide et des performances robustes.",
"templates": "Templates Open Source",
"templatesSummary": "Déployez des templates open source en un clic.",
"templatesDes": "Déployez des templates open source en un clic, grâce à Docker Compose (Plausible, Calcom, Pocketbase, etc.).",
"traefik": "Configuration Traefik en temps réel",
"traefikSummary": "Modifiez les paramètres de Traefik à la volée via une interface graphique ou une API.",
"traefikDes": "Les utilisateurs peuvent ajuster la configuration de Traefik, y compris les middlewares, règles de redirection et certificats SSL, via une interface intuitive ou une API. Cette fonctionnalité permet un routage du trafic et des ajustements de sécurité sans redémarrer les services.",
"users": "Gestion des permissions utilisateurs",
"usersSummary": "Contrôle détaillé des permissions des utilisateurs pour accéder et gérer les projets et services.",
"usersDes": "Permet aux administrateurs de définir des rôles et des permissions spécifiques pour chaque utilisateur, y compris la création, modification ou suppression d'applications et de bases de données. Cette fonctionnalité assure une gestion sécurisée et efficace des équipes larges et diversifiées.",
"terminal": "Accès au terminal",
"terminalSummary": "Accès direct au terminal de chaque conteneur et serveur pour une gestion avancée.",
"terminalDes": "Fournit une interface permettant d'accéder à la ligne de commande de tout conteneur actif, offrant aux développeurs la possibilité d'exécuter des commandes, de gérer des services et de résoudre les problèmes directement depuis le tableau de bord."
},
"callToAction": {
"title": "Libérez le potentiel de vos déploiements avec Dokploy Cloud",
"des": "Dites adieu aux tracas d'infrastructure — Dokploy Cloud s'occupe de tout. Déployez et gérez facilement vos conteneurs Docker et sécurisez votre trafic avec Traefik. Concentrez-vous sur la création, nous nous chargeons du reste.",
"button": "Commencer maintenant"
},
"faq": {
"title": "Questions fréquemment posées",
"des": "Si vous ne trouvez pas ce que vous cherchez, veuillez soumettre un problème via notre dépôt GitHub ou poser vos questions sur notre Discord.",
"q1": "Qu'est-ce que Dokploy ?",
"a1": "Dokploy est une solution de déploiement stable et facile à utiliser, conçue pour simplifier la gestion des applications. Pensez à Dokploy comme une alternative gratuite et auto-hébergeable à des plateformes comme Heroku, Vercel et Netlify.",
"q2": "Pourquoi choisir Dokploy ?",
"a2": "Dokploy offre simplicité, flexibilité et rapidité dans le déploiement et la gestion des applications.",
"q4": "Est-ce open source ?",
"a4": "Oui, Dokploy est open source et gratuit à utiliser.",
"q5": "Quels types de langages puis-je déployer avec Dokploy ?",
"a5": "Dokploy ne restreint pas les langages de programmation. Vous êtes libre de choisir votre langage et framework préférés.",
"q6": "Comment demander une fonctionnalité ou signaler un bug ?",
"a6": "Pour demander une fonctionnalité ou signaler un bug, veuillez créer un problème sur notre dépôt GitHub ou poser la question sur notre chaîne Discord.",
"q7": "Suivez-vous l'utilisation de Dokploy ?",
"a7": "Non, nous ne suivons aucune donnée d'utilisation.",
"q8": "Existe-t-il des forums ou communautés où je peux interagir avec d'autres utilisateurs ?",
"a8": "Oui, nous avons des discussions actives sur GitHub et Discord où vous pouvez partager des idées, demander de l'aide et vous connecter avec d'autres utilisateurs.",
"q9": "Quels types d'applications puis-je déployer avec Dokploy ?",
"a9": "Vous pouvez déployer toute application pouvant être Dockerisée, sans aucune limite. Dokploy prend en charge les builds à partir de dépôts Git, Dockerfiles, Nixpacks et Buildpacks comme Heroku et Paketo.",
"q10": "Comment Dokploy gère-t-il la gestion des bases de données ?",
"a10": "Dokploy prend en charge plusieurs systèmes de bases de données, notamment Postgres, MySQL, MariaDB, MongoDB et Redis, avec des outils pour un déploiement facile, une gestion et des sauvegardes directement depuis le tableau de bord.",
"q11": "Comment fonctionne le plan Open Source de Dokploy ?",
"a11": "Vous pouvez héberger l'interface utilisateur de Dokploy sur votre propre infrastructure et vous serez responsable de sa maintenance et de ses mises à jour.",
"q12": "Dois-je fournir mon propre serveur pour le plan géré ?",
"a12": "Oui, dans le plan géré, vous fournissez votre propre serveur (par exemple, Hetzner, Hostinger, AWS, etc.) VPS, et nous gérons l'infrastructure de l'interface utilisateur de Dokploy pour vous.",
"q13": "Que se passe-t-il si j'ai besoin de plus d'un serveur ?",
"a13": "Le premier serveur coûte 4,50 $/mois, et si vous en achetez plus d'un, cela coûtera 3,50 $/mois par serveur.",
"q14": "Y a-t-il une limite au nombre de déploiements ?",
"a14": "Non, il n'y a aucune limite au nombre de déploiements dans aucun des plans.",
"q15": "Que se passe-t-il si je dépasse la limite de serveurs achetés ?",
"a15": "Les serveurs ajoutés le plus récemment seront désactivés. Vous ne pourrez pas créer de services sur des serveurs inactifs tant qu'ils ne seront pas réactivés.",
"q16": "Proposez-vous des remboursements ?",
"a16": "Nous ne proposons pas de remboursements. Cependant, vous pouvez annuler votre abonnement à tout moment. N'hésitez pas à essayer notre version open source gratuitement avant d'effectuer un achat.",
"q17": "Quel type de support proposez-vous ?",
"a17": "Nous offrons un support communautaire pour la version open source et un support prioritaire pour les plans payants (via Discord ou email à support@dokploy.com).",
"q18": "Quel est le piège du plan payant ?",
"a18": "Aucun. Vous connectez votre serveur (VPS) à votre compte et vous pouvez déployer des applications, bases de données et utilisateurs illimités tout en bénéficiant de mises à jour, déploiements, sauvegardes et bien plus encore."
},
"footer": {
"copyright": "Copyright © {year} Dokploy. Tous droits réservés."
}
},
"404": {
"title": "Oups ! On dirait que vous êtes perdu.",
"des": "Revenons là où vous étiez",
"action": "par ici"
},
"Link": {
"docs": {
"intro": "https://docs.dokploy.com/docs/core",
"install": "https://docs.dokploy.com/docs/core/installation"
}
},
"Pricing": {
"swirlyDoodleTitle": "Simple et abordable,",
"restTitle": "Tarifs.",
"description": "Déployer plus intelligemment, S'étendre plus rapidement Sans se ruiner",
"billingCycle": {
"monthly": "Mensuel",
"annual": "Annuel"
},
"plan": {
"free": {
"title": "Gratuit",
"subTitle": "Open Source",
"section": {
"title": "Dokploy Open Source",
"description": "Gérer sa propre infrastructure installer dokploy ui sur son propre serveur."
},
"features": {
"f1": "Complete Flexibility: Install Dokploy UI on your own infrastructure",
"f2": "Infrastructure Auto-Hébergée",
"f3": "Support de la communauté",
"f4": "Accès à toutes les fonctionnalités",
"f5": "Accès à toutes les mises à jour",
"f9": "Serveurs Illimitées"
},
"go": "Installation"
},
"cloud": {
"title": "Recommandé",
"section": {
"title": "Offre Dokploy&",
"description": " pour gérer l'infrastructure de Dokploy UI, nous nous en occupons pour vous."
},
"servers": "{serverQuantity} Serveurs (Vous fournissez les serveurs)",
"features": {
"f1": "Hébergement géré: Pas besoin de gérer vos propres serveurs",
"f2": "Déploiements Illimités",
"f3": "Bases de données Illimitées",
"f4": "Applications Illimitées",
"f5": "Utilisateurs Illimités",
"f6": "Support Prioritaire",
"f7": "Nouvelles mises à jour"
},
"go": "S'abonner"
}
},
"faq": {
"title": "Questions fréquemment posées",
"description": "Si vous ne trouvez pas ce que vous cherchez, veuillez nous envoyer un e-mail à",
"q1": "Comment fonctionne l'offre Open Source de Dokploy ?",
"a1": "Vous pouvez héberger l'interface utilisateur de Dokploy sur votre propre infrastructure et vous serez responsable de la maintenance et des mises à jour.",
"q2": "Dois-je fournir mon propre serveur pour l'offre gérée ?",
"a2": "Oui, dans l'offre gérée, vous fournissez votre propre serveur (par exemple, Hetzner, Hostinger, AWS, etc.) VPS, et nous gérons l'infrastructure de l'interface utilisateur de Dokploy pour vous.",
"q3": "Que se passe-t-il si j'ai besoin de plus d'un serveur ?",
"a3": "Le premier serveur coûte 4,50 $/mois. Si vous en achetez plus d'un, il vous reviendra à 3,50 $/mois par serveur.",
"q4": "Y a-t-il une limite de déploiements ?",
"a4": "Non, il n'y a aucune limite de déploiements dans aucun des plans.",
"q5": "Que se passe-t-il si je dépasse la limite du serveur que j'ai acheté ?",
"a5": "Les derniers serveurs ajoutés seront désactivés. Vous ne pourrez pas créer de services sur les serveurs inactifs tant qu'ils n'auront pas été réactivés.",
"q6": "Proposez-vous des remboursements ?",
"a6": "Nous n'acceptons pas les remboursements. Cependant, vous pouvez annuler votre abonnement à tout moment. N'hésitez pas à essayer gratuitement la version open-source avant de passer à l'achat.",
"q7": "Quel type de support proposez-vous ?",
"a7": "Nous offrons un support communautaire pour la version open-source et un support prioritaire pour les offres payantes.",
"q8": "Dokploy est-il open-source ?",
"a8": "Oui, Dokploy est entièrement open-source. Vous pouvez contribuer ou modifier selon vos besoins pour vos projets."
}
},
"blog": {
"title": "Blog",
"description": "Dernières nouvelles, mises à jour et articles de Dokploy",
"noPosts": "Aucun article disponible",
"noResults": "Aucun article ne correspond à vos critères",
"searchPlaceholder": "Rechercher des articles...",
"allTags": "Tous les tags",
"relatedPosts": "Articles similaires",
"tagDescription": "Articles tagués avec"
},
"Contact": {
"title": "Nous contacter",
"description": "Contactez notre équipe. Nous sommes là pour vous aider avec toutes vos questions sur Dokploy.",
"successTitle": "Merci de nous avoir contactés !",
"successMessage": "Nous avons reçu votre message et vous répondrons dans les plus brefs délais.",
"errorMessage": "Il y a eu une erreur lors de l'envoi de votre message. Veuillez réessayer.",
"fields": {
"inquiryType": {
"label": "Comment pouvons-nous vous aider aujourd'hui ?",
"placeholder": "Sélectionnez une option",
"options": {
"support": "Support",
"sales": "Ventes",
"other": "Autre"
}
},
"firstName": {
"label": "Prénom",
"placeholder": "Votre prénom"
},
"lastName": {
"label": "Nom de famille",
"placeholder": "Votre nom de famille"
},
"email": {
"label": "Email",
"placeholder": "votre.email@entreprise.com"
},
"company": {
"label": "Nom de l'entreprise",
"placeholder": "Le nom de votre entreprise"
},
"message": {
"label": "Comment pouvons-nous vous aider ?",
"placeholder": "Parlez-nous de votre demande..."
}
},
"buttons": {
"send": "Envoyer le message",
"sending": "Envoi en cours...",
"sendAnother": "Envoyer un autre message"
},
"errors": {
"inquiryTypeRequired": "Veuillez sélectionner comment nous pouvons vous aider",
"firstNameRequired": "Le prénom est obligatoire",
"lastNameRequired": "Le nom de famille est obligatoire",
"emailRequired": "L'email est obligatoire",
"emailInvalid": "Veuillez saisir une adresse email valide",
"companyRequired": "Le nom de l'entreprise est obligatoire",
"messageRequired": "Le message est obligatoire"
}
}
}

View File

@@ -1,277 +0,0 @@
{
"HomePage": {
"navigation": {
"features": "特性",
"faqs": "FAQ",
"docs": "文档",
"pricing": "价格",
"support": "赞助",
"dashboard": "控制台",
"discord": "Discord",
"i18nButtonPlaceholder": "语言",
"i18nFr": "Français",
"i18nEn": "English",
"i18nEs": "Español",
"i18nZh-Hans": "简体中文",
"blog": "博客",
"home": "首页",
"login": "登录",
"register": "注册",
"contact": "联系我们"
},
"hero": {
"cloud": "隆重介绍 Dokploy 云",
"deploy": "部署在",
"anywhere": "任何设施之上",
"with": "",
"des": "以前所未有的简洁和高效提供一站式项目、数据的管理以及系统监控。",
"featuredIn": "发布于",
"sponsors": {
"title": "赞助名单",
"description": "Dokploy 是由社区成员共同支持的完全免费的开源项目,您的慷慨解囊将帮助我们继续开发和改进 Dokploy。",
"level": {
"hero": "特别赞助",
"premium": "金牌赞助",
"supporting": "银牌赞助",
"community": "铜牌赞助",
"organizations": "组织赞助",
"individuals": "个人赞助"
}
}
},
"primaryFeatures": {
"title": "全面掌控您的基础设施",
"des": "Dokploy 不仅简化您的项目部署和数据管理流程,同时还提供完备的数据备份,一切只在弹指间。",
"projects": "项目",
"logs": "日志",
"templates": "模板",
"templatesDes": "一键部署热门开源项目。",
"logsDes": "轻松监控和处理您的应用程序日志,确保高效故障排除和最佳性能。",
"projectsDes": "您所有的项目和所需的一切信息都将归集一处。",
"applications": "应用和数据库",
"applicationsDes": "Dokploy 通过集中管理您的应用和数据库来提升安全性和效率,并大大简化了跨基础设施的访问和管理。",
"compose": "Docker Compose",
"composeDes": "Dokploy 提供对复杂应用和服务的原生 Docker Compose 支持。",
"multiserver": "多服务器部署",
"multiserverDes": "毫不费力地将应用程序部署到多个服务器上。",
"monitoring": "监控",
"monitoringDes": "随时掌控你的系统性能和应用健康,确保服务无间断运行。",
"backups": "备份",
"backupsDes": "使用 Dokploy 的自动备份功能来保护您的数据,并在需要时极速还原。",
"traefik": "Traefik",
"traefikDes": "使用我们的编辑器轻松管理你的域名、证书和其他设置。"
},
"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。我们还提供方便的图形化管理工具以供使用。",
"q11": "Dokploy 的开源版本是什么?",
"a11": "您可以免费安装 Dokploy 开源版本,并自行负责 Dokploy 的日后维护工作",
"q12": "付费计划还需要自己的服务器吗?",
"a12": "是的在付费计划中您依然需要提供您用于实际运行服务的服务器如阿里云、腾讯云、AWS 等),我们会为您管理 Dokploy 控制面板。",
"q13": "如果我需要管理更多的服务器怎么办?",
"a13": "第一台服务器的费用为 $4.5/月,之后每台的费用是 $3.5/月。",
"q14": "部署服务的数量有限制吗?",
"a14": "不管您如何使用 Dokploy我们都不会限制您部署服务的数量。",
"q15": "如果我意外超过了最大服务器数量怎么办?",
"a15": "最新添加的服务器将被停用,您将不能向其创建服务,直到它们被重新激活。",
"q16": "关于退款服务的政策?",
"a16": "您可以随时取消您的订阅,但请原谅我们无法提供退款服务,您可以无限试用开源版本,然后再购买。",
"q17": "关于技术支持?",
"a17": "付费计划可以得到优先的技术支持,开源版本则是由社区提供技术支持。",
"q18": "Dokploy 开源吗?",
"a18": "是的Dokploy 完全开源,您可以参与贡献或者是 Fork 后自行修改以用于您的私人需求。"
},
"footer": {
"copyright": "版权属于 © {year} Dokploy 保留所有权利"
}
},
"404": {
"title": "糟糕!看起来你迷路了。",
"des": "让我们送你",
"action": "回家"
},
"Link": {
"docs": {
"intro": "https://docs.dokploy.com/docs/core",
"install": "https://docs.dokploy.com/docs/core/installation"
}
},
"Pricing": {
"swirlyDoodleTitle": "简洁明了的",
"restTitle": "定价",
"description": "更聪明的部署方式,更快的扩容速度,以及不会让你破产的账单。",
"billingCycle": {
"monthly": "按月",
"annual": "按年"
},
"plan": {
"free": {
"title": "免费",
"subTitle": "开源版本",
"section": {
"title": "部署Dokploy的开源版本",
"description": "自行管理您的基础设施,不收取任何费用"
},
"features": {
"f1": "灵活的架构,您可以单独部署 Dokploy 管理端",
"f2": "无限部署",
"f3": "您负责维护基础设施",
"f4": "来自社区的有限支持",
"f5": "所有功能可用",
"f6": "Dokploy 集成",
"f7": "基础备份服务",
"f8": "跟随开源版本更新",
"f9": "无限服务器数量"
},
"go": "立即开始"
},
"cloud": {
"title": "推荐(年付更优惠)",
"section": {
"title": "Dokploy 云",
"description": "使用我们的云服务,一站式管理您所有的部署。"
},
"servers": "{serverQuantity}台受控服务器",
"features": {
"f1": "由 Dokploy 云提供支持的独立控制面板",
"f2": "无限部署",
"f3": "无限数据库",
"f4": "无限应用",
"f5": "无限用户",
"f6": "优先技术支持",
"f7": "最新的功能特性"
},
"go": "订阅"
}
},
"faq": {
"title": "常见问题",
"description": "如果您的问题不在以下列表,请随时向我们致信",
"q1": "Dokploy 的开源版本是什么?",
"a1": "您可以免费安装 Dokploy 开源版本,并自行负责 Dokploy 的日后维护工作",
"q2": "付费计划还需要自己的服务器吗?",
"a2": "是的在付费计划中您依然需要提供您用于实际运行服务的服务器如阿里云、腾讯云、AWS 等),我们会为您管理 Dokploy 控制面板。",
"q3": "如果我需要管理更多的服务器怎么办?",
"a3": "第一台服务器的费用为 $4.5/月,之后每台的费用是 $3.5/月。",
"q4": "部署服务的数量有限制吗?",
"a4": "不管您如何使用 Dokploy我们都不会限制您部署服务的数量。",
"q5": "如果我意外超过了最大服务器数量怎么办?",
"a5": "最新添加的服务器将被停用,您将不能向其创建服务,直到它们被重新激活。",
"q6": "关于退款服务的政策?",
"a6": "您可以随时取消您的订阅,但请原谅我们无法提供退款服务,您可以无限试用开源版本,然后再购买。",
"q7": "关于技术支持?",
"a7": "付费计划可以得到优先的技术支持,开源版本则是由社区提供技术支持。",
"q8": "Dokploy 开源吗?",
"a8": "是的Dokploy 完全开源,您可以参与贡献或者是 Fork 后自行修改以用于您的私人需求。"
}
},
"blog": {
"title": "博客",
"description": "Dokploy 的最新消息、更新和文章",
"noPosts": "暂无文章",
"noResults": "没有找到符合条件的文章",
"searchPlaceholder": "搜索文章...",
"allTags": "所有标签",
"relatedPosts": "相关文章",
"tagDescription": "标签文章",
"readMore": "阅读更多",
"backToBlog": "返回博客",
"tags": "标签",
"postsTaggedWith": "标签为",
"foundPosts": "{count, plural, =0 {未找到文章} other {找到 # 篇文章}}",
"tagTitle": "标签为 {tag} 的文章"
},
"Contact": {
"title": "联系我们",
"description": "联系我们的团队。我们随时为您解答关于 Dokploy 的任何问题。",
"successTitle": "感谢您联系我们!",
"successMessage": "我们已收到您的消息,将尽快回复您。",
"errorMessage": "发送消息时出现错误,请重试。",
"fields": {
"inquiryType": {
"label": "我们今天可以为您提供什么帮助?",
"placeholder": "选择一个选项",
"options": {
"support": "技术支持",
"sales": "销售咨询",
"other": "其他"
}
},
"firstName": {
"label": "名",
"placeholder": "您的名"
},
"lastName": {
"label": "姓",
"placeholder": "您的姓"
},
"email": {
"label": "邮箱",
"placeholder": "your.email@company.com"
},
"company": {
"label": "公司名称",
"placeholder": "您的公司名称"
},
"message": {
"label": "我们如何帮助您?",
"placeholder": "请详细描述您的咨询..."
}
},
"buttons": {
"send": "发送消息",
"sending": "发送中...",
"sendAnother": "发送另一条消息"
},
"errors": {
"inquiryTypeRequired": "请选择我们可以为您提供的帮助",
"firstNameRequired": "名为必填项",
"lastNameRequired": "姓为必填项",
"emailRequired": "邮箱为必填项",
"emailInvalid": "请输入有效的邮箱地址",
"companyRequired": "公司名称为必填项",
"messageRequired": "消息为必填项"
}
}
}

View File

@@ -1,14 +0,0 @@
import createMiddleware from "next-intl/middleware";
export default createMiddleware({
locales: ["en", "fr", "es", "zh-Hans"],
// Used when no locale matches
defaultLocale: "en",
localePrefix: "as-needed",
});
export const config = {
// Match only internationalized pathnames
matcher: ["/((?!api|_next|.*\\..*).*)"],
};

View File

@@ -1,6 +1,4 @@
const createNextIntlPlugin = require("next-intl/plugin");
const withNextIntl = createNextIntlPlugin();
// Internationalization removed
/** @type {import('next').NextConfig} */
const nextConfig = {
@@ -12,13 +10,13 @@ const nextConfig = {
},
images: {
domains: [
"static.ghost.org",
"testing-ghost-8423be-31-220-108-27.traefik.me",
"images.unsplash.com",
"www.gravatar.com",
"cms.dokploy.com",
'static.ghost.org',
'testing-ghost-8423be-31-220-108-27.traefik.me',
'images.unsplash.com',
'www.gravatar.com',
'cms.dokploy.com',
],
},
};
}
module.exports = withNextIntl(nextConfig);
module.exports = nextConfig