diff --git a/messages/bg-BG.json b/messages/bg-BG.json
index 3717855e..e8c85487 100644
--- a/messages/bg-BG.json
+++ b/messages/bg-BG.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Redirecting to login...",
"autoLoginError": "Auto Login Error",
"autoLoginErrorNoRedirectUrl": "No redirect URL received from the identity provider.",
- "autoLoginErrorGeneratingUrl": "Failed to generate authentication URL."
+ "autoLoginErrorGeneratingUrl": "Failed to generate authentication URL.",
+ "internationaldomaindetected": "International Domain Detected",
+ "willbestoredas": "Will be stored as:"
}
diff --git a/messages/cs-CZ.json b/messages/cs-CZ.json
index fc03108a..fe9530d3 100644
--- a/messages/cs-CZ.json
+++ b/messages/cs-CZ.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Redirecting to login...",
"autoLoginError": "Auto Login Error",
"autoLoginErrorNoRedirectUrl": "No redirect URL received from the identity provider.",
- "autoLoginErrorGeneratingUrl": "Failed to generate authentication URL."
+ "autoLoginErrorGeneratingUrl": "Failed to generate authentication URL.",
+ "internationaldomaindetected": "Detekována mezinárodní doména",
+ "willbestoredas": "Bude uloženo jako:"
}
diff --git a/messages/de-DE.json b/messages/de-DE.json
index 062b61af..c79a5f64 100644
--- a/messages/de-DE.json
+++ b/messages/de-DE.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Weiterleitung zur Anmeldung...",
"autoLoginError": "Fehler bei der automatischen Anmeldung",
"autoLoginErrorNoRedirectUrl": "Keine Weiterleitungs-URL vom Identitätsanbieter erhalten.",
- "autoLoginErrorGeneratingUrl": "Fehler beim Generieren der Authentifizierungs-URL."
+ "autoLoginErrorGeneratingUrl": "Fehler beim Generieren der Authentifizierungs-URL.",
+ "internationaldomaindetected": "Internationale Domäne erkannt",
+ "willbestoredas": "Wird gespeichert als:"
}
diff --git a/messages/en-US.json b/messages/en-US.json
index f9bb4f6b..dbfa817e 100644
--- a/messages/en-US.json
+++ b/messages/en-US.json
@@ -1494,5 +1494,7 @@
"documentation": "documentation"
},
"convertButton": "Convert This Node to Managed Self-Hosted"
- }
+ },
+ "internationaldomaindetected": "International Domain Detected",
+ "willbestoredas": "Will be stored as:"
}
diff --git a/messages/es-ES.json b/messages/es-ES.json
index 2b49d9bb..0bb67191 100644
--- a/messages/es-ES.json
+++ b/messages/es-ES.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Redirigiendo al inicio de sesión...",
"autoLoginError": "Error de inicio de sesión automático",
"autoLoginErrorNoRedirectUrl": "No se recibió URL de redirección del proveedor de identidad.",
- "autoLoginErrorGeneratingUrl": "Error al generar URL de autenticación."
+ "autoLoginErrorGeneratingUrl": "Error al generar URL de autenticación.",
+ "internationaldomaindetected": "Dominio internacional detectado",
+ "willbestoredas": "Se almacenará como: "
}
diff --git a/messages/fr-FR.json b/messages/fr-FR.json
index ee08d77b..28bcce6a 100644
--- a/messages/fr-FR.json
+++ b/messages/fr-FR.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Redirection vers la connexion...",
"autoLoginError": "Erreur de connexion automatique",
"autoLoginErrorNoRedirectUrl": "Aucune URL de redirection reçue du fournisseur d'identité.",
- "autoLoginErrorGeneratingUrl": "Échec de la génération de l'URL d'authentification."
+ "autoLoginErrorGeneratingUrl": "Échec de la génération de l'URL d'authentification.",
+ "internationaldomaindetected": "Domaine international détecté",
+ "willbestoredas": "Sera stocké comme:"
}
diff --git a/messages/it-IT.json b/messages/it-IT.json
index 83708597..b41079c3 100644
--- a/messages/it-IT.json
+++ b/messages/it-IT.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Reindirizzamento al login...",
"autoLoginError": "Errore di Accesso Automatico",
"autoLoginErrorNoRedirectUrl": "Nessun URL di reindirizzamento ricevuto dal provider di identità.",
- "autoLoginErrorGeneratingUrl": "Impossibile generare l'URL di autenticazione."
+ "autoLoginErrorGeneratingUrl": "Impossibile generare l'URL di autenticazione.",
+ "internationaldomaindetected": "Rilevato dominio internazionale",
+ "willbestoredas": "Verrà archiviato come:"
}
diff --git a/messages/ko-KR.json b/messages/ko-KR.json
index b13dd19d..4b27bf55 100644
--- a/messages/ko-KR.json
+++ b/messages/ko-KR.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "로그인으로 리디렉션 중...",
"autoLoginError": "자동 로그인 오류",
"autoLoginErrorNoRedirectUrl": "ID 공급자로부터 리디렉션 URL을 받지 못했습니다.",
- "autoLoginErrorGeneratingUrl": "인증 URL 생성 실패."
+ "autoLoginErrorGeneratingUrl": "인증 URL 생성 실패.",
+ "internationaldomaindetected": "국제 도메인 감지됨",
+ "willbestoredas": "다음과 같이 저장됩니다."
}
diff --git a/messages/nl-NL.json b/messages/nl-NL.json
index 76c28cb5..91e0be86 100644
--- a/messages/nl-NL.json
+++ b/messages/nl-NL.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Redirecting naar inloggen...",
"autoLoginError": "Auto Login Fout",
"autoLoginErrorNoRedirectUrl": "Geen redirect URL ontvangen van de identity provider.",
- "autoLoginErrorGeneratingUrl": "Genereren van authenticatie-URL mislukt."
+ "autoLoginErrorGeneratingUrl": "Genereren van authenticatie-URL mislukt.",
+ "internationaldomaindetected": "Internationaal Domein Gedetecteerd",
+ "willbestoredas": "Wordt opgeslagen als:"
}
diff --git a/messages/pl-PL.json b/messages/pl-PL.json
index be33709c..9491a94d 100644
--- a/messages/pl-PL.json
+++ b/messages/pl-PL.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Przekierowanie do logowania...",
"autoLoginError": "Błąd automatycznego logowania",
"autoLoginErrorNoRedirectUrl": "Nie otrzymano URL przekierowania od dostawcy tożsamości.",
- "autoLoginErrorGeneratingUrl": "Nie udało się wygenerować URL uwierzytelniania."
+ "autoLoginErrorGeneratingUrl": "Nie udało się wygenerować URL uwierzytelniania.",
+ "internationaldomaindetected": "Wykryto domenę międzynarodową",
+ "willbestoredas": "Będzie przechowywane jako:"
}
diff --git a/messages/pt-PT.json b/messages/pt-PT.json
index 4efd0237..050280fa 100644
--- a/messages/pt-PT.json
+++ b/messages/pt-PT.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Redirecionando para login...",
"autoLoginError": "Erro de Login Automático",
"autoLoginErrorNoRedirectUrl": "Nenhum URL de redirecionamento recebido do provedor de identidade.",
- "autoLoginErrorGeneratingUrl": "Falha ao gerar URL de autenticação."
+ "autoLoginErrorGeneratingUrl": "Falha ao gerar URL de autenticação.",
+ "internationaldomaindetected": "Domínio internacional detetado",
+ "willbestoredas": "Será armazenado como:"
}
diff --git a/messages/ru-RU.json b/messages/ru-RU.json
index ed44702d..eef9aad6 100644
--- a/messages/ru-RU.json
+++ b/messages/ru-RU.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Перенаправление к входу...",
"autoLoginError": "Ошибка автоматического входа",
"autoLoginErrorNoRedirectUrl": "URL-адрес перенаправления не получен от провайдера удостоверения.",
- "autoLoginErrorGeneratingUrl": "Не удалось сгенерировать URL-адрес аутентификации."
+ "autoLoginErrorGeneratingUrl": "Не удалось сгенерировать URL-адрес аутентификации.",
+ "internationaldomaindetected": "Обнаружен международный домен",
+ "willbestoredas": "Будет сохранен как:"
}
diff --git a/messages/tr-TR.json b/messages/tr-TR.json
index 89de6876..09115e9a 100644
--- a/messages/tr-TR.json
+++ b/messages/tr-TR.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "Girişe yönlendiriliyorsunuz...",
"autoLoginError": "Otomatik Giriş Hatası",
"autoLoginErrorNoRedirectUrl": "Kimlik sağlayıcıdan yönlendirme URL'si alınamadı.",
- "autoLoginErrorGeneratingUrl": "Kimlik doğrulama URL'si oluşturulamadı."
+ "autoLoginErrorGeneratingUrl": "Kimlik doğrulama URL'si oluşturulamadı.",
+ "internationaldomaindetected": "Uluslararası Etki Alanı Algılandı",
+ "willbestoredas": "Şu şekilde saklanacaktır:"
}
diff --git a/messages/zh-CN.json b/messages/zh-CN.json
index 06cd8549..dee4cff1 100644
--- a/messages/zh-CN.json
+++ b/messages/zh-CN.json
@@ -1457,5 +1457,7 @@
"autoLoginRedirecting": "重定向到登录...",
"autoLoginError": "自动登录错误",
"autoLoginErrorNoRedirectUrl": "未从身份提供商收到重定向URL。",
- "autoLoginErrorGeneratingUrl": "生成身份验证URL失败。"
+ "autoLoginErrorGeneratingUrl": "生成身份验证URL失败。",
+ "internationaldomaindetected": "检测到国际域名",
+ "willbestoredas": "将存储为:"
}
diff --git a/src/app/[orgId]/settings/domains/CreateDomainForm.tsx b/src/app/[orgId]/settings/domains/CreateDomainForm.tsx
index 31bf82f1..60b5fa02 100644
--- a/src/app/[orgId]/settings/domains/CreateDomainForm.tsx
+++ b/src/app/[orgId]/settings/domains/CreateDomainForm.tsx
@@ -7,12 +7,13 @@ import {
FormField,
FormItem,
FormLabel,
- FormMessage
+ FormMessage,
+ FormDescription
} from "@app/components/ui/form";
import { Input } from "@app/components/ui/input";
import { useToast } from "@app/hooks/useToast";
import { zodResolver } from "@hookform/resolvers/zod";
-import { useState } from "react";
+import { useState, useMemo } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import {
@@ -33,7 +34,7 @@ import { CreateDomainResponse } from "@server/routers/domain/createOrgDomain";
import { StrategySelect } from "@app/components/StrategySelect";
import { AxiosResponse } from "axios";
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
-import { InfoIcon, AlertTriangle } from "lucide-react";
+import { InfoIcon, AlertTriangle, Globe } from "lucide-react";
import CopyToClipboard from "@app/components/CopyToClipboard";
import {
InfoSection,
@@ -43,9 +44,58 @@ import {
} from "@app/components/InfoSection";
import { useOrgContext } from "@app/hooks/useOrgContext";
import { build } from "@server/build";
+import { toASCII, toUnicode } from 'punycode';
+
+
+// Helper functions for Unicode domain handling
+function toPunycode(domain: string): string {
+ try {
+ const parts = toASCII(domain);
+ return parts;
+ } catch (error) {
+ return domain.toLowerCase();
+ }
+}
+
+function fromPunycode(domain: string): string {
+ try {
+ const parts = toUnicode(domain)
+ return parts;
+ } catch (error) {
+ return domain;
+ }
+}
+
+function isValidDomainFormat(domain: string): boolean {
+ const unicodeRegex = /^(?!:\/\/)([^\s.]+\.)*[^\s.]+$/;
+
+ if (!unicodeRegex.test(domain)) {
+ return false;
+ }
+
+ const parts = domain.split('.');
+ for (const part of parts) {
+ if (part.length === 0 || part.startsWith('-') || part.endsWith('-')) {
+ return false;
+ }
+ if (part.length > 63) {
+ return false;
+ }
+ }
+
+ if (domain.length > 253) {
+ return false;
+ }
+
+ return true;
+}
const formSchema = z.object({
- baseDomain: z.string().min(1, "Domain is required"),
+ baseDomain: z
+ .string()
+ .min(1, "Domain is required")
+ .refine((val) => isValidDomainFormat(val), "Invalid domain format")
+ .transform((val) => toPunycode(val)),
type: z.enum(["ns", "cname", "wildcard"])
});
@@ -109,8 +159,14 @@ export default function CreateDomainForm({
}
}
- const domainType = form.watch("type");
const baseDomain = form.watch("baseDomain");
+ const domainInputValue = form.watch("baseDomain") || "";
+
+ const punycodePreview = useMemo(() => {
+ if (!domainInputValue) return "";
+ const punycode = toPunycode(domainInputValue);
+ return punycode !== domainInputValue.toLowerCase() ? punycode : "";
+ }, [domainInputValue]);
let domainOptions: any = [];
if (build == "enterprise" || build == "saas") {
@@ -182,10 +238,23 @@ export default function CreateDomainForm({
{t("willbestoredas")} {punycodePreview}
{t("domainPickerEnterSubdomainOrLeaveBlank")} @@ -474,7 +487,7 @@ export default function DomainPicker2({ {selectedBaseDomain ? (