diff --git a/.circleci/config.yml b/.circleci/config.yml index c5e57a973..25982d59b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -99,14 +99,14 @@ workflows: only: - main - canary - - fix/build-i18n + - refactor/enhancement-languages - build-arm64: filters: branches: only: - main - canary - - fix/build-i18n + - refactor/enhancement-languages - combine-manifests: requires: - build-amd64 @@ -116,4 +116,4 @@ workflows: only: - main - canary - - fix/build-i18n + - refactor/enhancement-languages diff --git a/Dockerfile b/Dockerfile index 838fbe4f6..ebc61a2b7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ RUN apt-get update && apt-get install -y curl unzip apache2-utils && rm -rf /var COPY --from=build /prod/dokploy/.next ./.next COPY --from=build /prod/dokploy/dist ./dist COPY --from=build /prod/dokploy/next.config.mjs ./next.config.mjs -COPY --from=build /prod/dokploy/next-i18next.config.cjs ./next-i18next.config.cjs +# COPY --from=build /prod/dokploy/next-i18next.config.cjs ./next-i18next.config.cjs COPY --from=build /prod/dokploy/public ./public COPY --from=build /prod/dokploy/package.json ./package.json COPY --from=build /prod/dokploy/drizzle ./drizzle diff --git a/apps/dokploy/components/dashboard/settings/appearance-form.tsx b/apps/dokploy/components/dashboard/settings/appearance-form.tsx index 9f740efd8..209ac5421 100644 --- a/apps/dokploy/components/dashboard/settings/appearance-form.tsx +++ b/apps/dokploy/components/dashboard/settings/appearance-form.tsx @@ -32,30 +32,15 @@ import { useTranslation } from "next-i18next"; import { useTheme } from "next-themes"; import { useEffect } from "react"; import { toast } from "sonner"; +import { Languages } from "@/lib/languages"; const appearanceFormSchema = z.object({ theme: z.enum(["light", "dark", "system"], { required_error: "Please select a theme.", }), - language: z.enum( - [ - "en", - "pl", - "ru", - "fr", - "de", - "tr", - "zh-Hant", - "kz", - "zh-Hans", - "fa", - "ko", - "pt-br", - ], - { - required_error: "Please select a language.", - }, - ), + language: z.nativeEnum(Languages, { + required_error: "Please select a language.", + }), }); type AppearanceFormValues = z.infer; @@ -63,7 +48,7 @@ type AppearanceFormValues = z.infer; // This can come from your database or API. const defaultValues: Partial = { theme: "system", - language: "en", + language: Languages.English, }; export function AppearanceForm() { @@ -188,25 +173,15 @@ export function AppearanceForm() { - {[ - { label: "English", value: "en" }, - { label: "Polski", value: "pl" }, - { label: "Русский", value: "ru" }, - { label: "Français", value: "fr" }, - { label: "Deutsch", value: "de" }, - { label: "繁體中文", value: "zh-Hant" }, - { label: "简体中文", value: "zh-Hans" }, - { label: "Türkçe", value: "tr" }, - { label: "Қазақ", value: "tr" }, - { label: "Kazakh", value: "kz" }, - { label: "Persian", value: "fa" }, - { label: "한국어", value: "ko" }, - { label: "Português", value: "pt-br" }, - ].map((preset) => ( - - {preset.label} - - ))} + {Object.keys(Languages).map((preset) => { + const value = + Languages[preset as keyof typeof Languages]; + return ( + + {preset} + + ); + })} diff --git a/apps/dokploy/lib/languages.ts b/apps/dokploy/lib/languages.ts new file mode 100644 index 000000000..59bcc097d --- /dev/null +++ b/apps/dokploy/lib/languages.ts @@ -0,0 +1,16 @@ +export enum Languages { + English = "en", + Polish = "pl", + Russian = "ru", + French = "fr", + German = "de", + ChineseTraditional = "zh-Hant", + ChineseSimplified = "zh-Hans", + Turkish = "tr", + Kazakh = "kz", + Persian = "fa", + Korean = "ko", + Portuguese = "pt-br", +} + +export type Language = keyof typeof Languages; diff --git a/apps/dokploy/next-i18next.config.cjs b/apps/dokploy/next-i18next.config.cjs index fef1df4a2..fe1b53ace 100644 --- a/apps/dokploy/next-i18next.config.cjs +++ b/apps/dokploy/next-i18next.config.cjs @@ -1,3 +1,5 @@ + + /** @type {import('next-i18next').UserConfig} */ module.exports = { fallbackLng: "en", diff --git a/apps/dokploy/pages/_app.tsx b/apps/dokploy/pages/_app.tsx index 511ac93ba..8bea3898b 100644 --- a/apps/dokploy/pages/_app.tsx +++ b/apps/dokploy/pages/_app.tsx @@ -10,6 +10,7 @@ import { Inter } from "next/font/google"; import Head from "next/head"; import Script from "next/script"; import type { ReactElement, ReactNode } from "react"; +import { Languages } from "@/lib/languages"; const inter = Inter({ subsets: ["latin"] }); @@ -71,20 +72,7 @@ export default api.withTRPC( { i18n: { defaultLocale: "en", - locales: [ - "en", - "pl", - "ru", - "fr", - "de", - "tr", - "kz", - "zh-Hant", - "zh-Hans", - "fa", - "ko", - "pt-br", - ], + locales: Object.values(Languages), localeDetection: false, }, fallbackLng: "en", diff --git a/apps/dokploy/public/locales/pt-br/settings.json b/apps/dokploy/public/locales/pt-br/settings.json index fc964be6c..7a00fd388 100644 --- a/apps/dokploy/public/locales/pt-br/settings.json +++ b/apps/dokploy/public/locales/pt-br/settings.json @@ -32,7 +32,7 @@ "settings.profile.password": "Senha", "settings.profile.avatar": "Avatar", - "settings.appearance.title": "Aparência", + "settings.appearance.title": "Aparencia", "settings.appearance.description": "Personalize o tema do seu dashboard.", "settings.appearance.theme": "Tema", "settings.appearance.themeDescription": "Selecione um tema para o dashboard", diff --git a/apps/dokploy/utils/hooks/use-locale.ts b/apps/dokploy/utils/hooks/use-locale.ts index 134418fcf..de979f7bf 100644 --- a/apps/dokploy/utils/hooks/use-locale.ts +++ b/apps/dokploy/utils/hooks/use-locale.ts @@ -1,26 +1,10 @@ +import type { Languages } from "@/lib/languages"; import Cookies from "js-cookie"; -const SUPPORTED_LOCALES = [ - "en", - "pl", - "ru", - "fr", - "de", - "tr", - "kz", - "zh-Hant", - "zh-Hans", - "fa", - "ko", - "pt-br", -] as const; - -type Locale = (typeof SUPPORTED_LOCALES)[number]; - export default function useLocale() { - const currentLocale = (Cookies.get("DOKPLOY_LOCALE") ?? "en") as Locale; + const currentLocale = (Cookies.get("DOKPLOY_LOCALE") ?? "en") as Languages; - const setLocale = (locale: Locale) => { + const setLocale = (locale: Languages) => { Cookies.set("DOKPLOY_LOCALE", locale, { expires: 365 }); window.location.reload(); }; diff --git a/apps/dokploy/utils/i18n.ts b/apps/dokploy/utils/i18n.ts index 4790f1a70..08370766e 100644 --- a/apps/dokploy/utils/i18n.ts +++ b/apps/dokploy/utils/i18n.ts @@ -5,11 +5,19 @@ export function getLocale(cookies: NextApiRequestCookies) { return locale; } -// libs/i18n.js import { serverSideTranslations as originalServerSideTranslations } from "next-i18next/serverSideTranslations"; -import nextI18NextConfig from "../next-i18next.config.cjs"; +import { Languages } from "@/lib/languages"; export const serverSideTranslations = ( locale: string, namespaces = ["common"], -) => originalServerSideTranslations(locale, namespaces, nextI18NextConfig); +) => + originalServerSideTranslations(locale, namespaces, { + fallbackLng: "en", + keySeparator: false, + i18n: { + defaultLocale: "en", + locales: Object.values(Languages), + localeDetection: false, + }, + });