Merge branch 'dev' into clients-pops

This commit is contained in:
miloschwartz 2025-06-22 17:50:39 -04:00
commit 0e87b6e48b
No known key found for this signature in database
21 changed files with 231 additions and 208 deletions

View file

@ -21,4 +21,4 @@ update-versions:
echo "Updated main.go with latest versions" echo "Updated main.go with latest versions"
put-back: put-back:
mv main.go.bak main.go mv main.go.bak main.go

View file

@ -4,7 +4,6 @@
app: app:
dashboard_url: "https://{{.DashboardDomain}}" dashboard_url: "https://{{.DashboardDomain}}"
log_level: "info" log_level: "info"
save_logs: false
domains: domains:
domain1: domain1:
@ -12,44 +11,21 @@ domains:
cert_resolver: "letsencrypt" cert_resolver: "letsencrypt"
server: server:
external_port: 3000 secret: "{{.Secret}}"
internal_port: 3001
next_port: 3002
internal_hostname: "pangolin"
session_cookie_name: "p_session_token"
resource_access_token_param: "p_token"
resource_access_token_headers:
id: "P-Access-Token-Id"
token: "P-Access-Token"
resource_session_request_param: "p_session_request"
secret: {{.Secret}}
cors: cors:
origins: ["https://{{.DashboardDomain}}"] origins: ["https://{{.DashboardDomain}}"]
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"] methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
allowed_headers: ["X-CSRF-Token", "Content-Type"] allowed_headers: ["X-CSRF-Token", "Content-Type"]
credentials: false credentials: false
traefik:
cert_resolver: "letsencrypt"
http_entrypoint: "web"
https_entrypoint: "websecure"
gerbil: gerbil:
start_port: 51820 start_port: 51820
base_endpoint: "{{.DashboardDomain}}" base_endpoint: "{{.DashboardDomain}}"
use_subdomain: false
block_size: 24
site_block_size: 30
subnet_group: 100.89.137.0/20
orgs: orgs:
block_size: 24 block_size: 24
subnet_group: 100.89.138.0/20 subnet_group: 100.89.138.0/20
rate_limits:
global:
window_minutes: 1
max_requests: 500
{{if .EnableEmail}} {{if .EnableEmail}}
email: email:
smtp_host: "{{.EmailSMTPHost}}" smtp_host: "{{.EmailSMTPHost}}"
@ -61,7 +37,7 @@ email:
flags: flags:
require_email_verification: {{.EnableEmail}} require_email_verification: {{.EnableEmail}}
disable_signup_without_invite: {{.DisableSignupWithoutInvite}} disable_signup_without_invite: true
disable_user_create_org: {{.DisableUserCreateOrg}} disable_user_create_org: false
allow_raw_resources: true allow_raw_resources: true
allow_base_domain_resources: true allow_base_domain_resources: true

View file

@ -39,8 +39,6 @@ type Config struct {
BaseDomain string BaseDomain string
DashboardDomain string DashboardDomain string
LetsEncryptEmail string LetsEncryptEmail string
DisableSignupWithoutInvite bool
DisableUserCreateOrg bool
EnableEmail bool EnableEmail bool
EmailSMTPHost string EmailSMTPHost string
EmailSMTPPort int EmailSMTPPort int
@ -72,15 +70,15 @@ func main() {
} }
var config Config var config Config
// check if there is already a config file // check if there is already a config file
if _, err := os.Stat("config/config.yml"); err != nil { if _, err := os.Stat("config/config.yml"); err != nil {
config = collectUserInput(reader) config = collectUserInput(reader)
loadVersions(&config) loadVersions(&config)
config.DoCrowdsecInstall = false config.DoCrowdsecInstall = false
config.Secret = generateRandomSecretKey() config.Secret = generateRandomSecretKey()
if err := createConfigFiles(config); err != nil { if err := createConfigFiles(config); err != nil {
fmt.Printf("Error creating config files: %v\n", err) fmt.Printf("Error creating config files: %v\n", err)
os.Exit(1) os.Exit(1)
@ -234,14 +232,9 @@ func collectUserInput(reader *bufio.Reader) Config {
config.LetsEncryptEmail = readString(reader, "Enter email for Let's Encrypt certificates", "") config.LetsEncryptEmail = readString(reader, "Enter email for Let's Encrypt certificates", "")
config.InstallGerbil = readBool(reader, "Do you want to use Gerbil to allow tunneled connections", true) config.InstallGerbil = readBool(reader, "Do you want to use Gerbil to allow tunneled connections", true)
// Security settings
fmt.Println("\n=== Security Settings ===")
config.DisableSignupWithoutInvite = readBool(reader, "Disable signup without invite", true)
config.DisableUserCreateOrg = readBool(reader, "Disable users from creating organizations", false)
// Email configuration // Email configuration
fmt.Println("\n=== Email Configuration ===") fmt.Println("\n=== Email Configuration ===")
config.EnableEmail = readBool(reader, "Enable email functionality", false) config.EnableEmail = readBool(reader, "Enable email functionality (SMTP)", false)
if config.EnableEmail { if config.EnableEmail {
config.EmailSMTPHost = readString(reader, "Enter SMTP host", "") config.EmailSMTPHost = readString(reader, "Enter SMTP host", "")
@ -353,7 +346,7 @@ func installDocker() error {
return fmt.Errorf("failed to detect Linux distribution: %v", err) return fmt.Errorf("failed to detect Linux distribution: %v", err)
} }
osRelease := string(output) osRelease := string(output)
// Detect system architecture // Detect system architecture
archCmd := exec.Command("uname", "-m") archCmd := exec.Command("uname", "-m")
archOutput, err := archCmd.Output() archOutput, err := archCmd.Output()
@ -361,7 +354,7 @@ func installDocker() error {
return fmt.Errorf("failed to detect system architecture: %v", err) return fmt.Errorf("failed to detect system architecture: %v", err)
} }
arch := strings.TrimSpace(string(archOutput)) arch := strings.TrimSpace(string(archOutput))
// Map architecture to Docker's architecture naming // Map architecture to Docker's architecture naming
var dockerArch string var dockerArch string
switch arch { switch arch {
@ -403,7 +396,7 @@ func installDocker() error {
fedoraVersion = v fedoraVersion = v
} }
} }
// Use appropriate DNF syntax based on version // Use appropriate DNF syntax based on version
var repoCmd string var repoCmd string
if fedoraVersion >= 41 { if fedoraVersion >= 41 {
@ -413,7 +406,7 @@ func installDocker() error {
// DNF 4 syntax for Fedora < 41 // DNF 4 syntax for Fedora < 41
repoCmd = "dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo" repoCmd = "dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo"
} }
installCmd = exec.Command("bash", "-c", fmt.Sprintf(` installCmd = exec.Command("bash", "-c", fmt.Sprintf(`
dnf -y install dnf-plugins-core && dnf -y install dnf-plugins-core &&
%s && %s &&
@ -442,7 +435,7 @@ func installDocker() error {
default: default:
return fmt.Errorf("unsupported Linux distribution") return fmt.Errorf("unsupported Linux distribution")
} }
installCmd.Stdout = os.Stdout installCmd.Stdout = os.Stdout
installCmd.Stderr = os.Stderr installCmd.Stderr = os.Stderr
return installCmd.Run() return installCmd.Run()
@ -527,7 +520,7 @@ func executeDockerComposeCommandWithArgs(args ...string) error {
return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available") return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available")
} }
} }
if useNewStyle { if useNewStyle {
cmd = exec.Command("docker", append([]string{"compose"}, args...)...) cmd = exec.Command("docker", append([]string{"compose"}, args...)...)
} else { } else {
@ -563,7 +556,7 @@ func startContainers() error {
// stopContainers stops the containers using the appropriate command. // stopContainers stops the containers using the appropriate command.
func stopContainers() error { func stopContainers() error {
fmt.Println("Stopping containers...") fmt.Println("Stopping containers...")
if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "down"); err != nil { if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "down"); err != nil {
return fmt.Errorf("failed to stop containers: %v", err) return fmt.Errorf("failed to stop containers: %v", err)
} }
@ -574,7 +567,7 @@ func stopContainers() error {
// restartContainer restarts a specific container using the appropriate command. // restartContainer restarts a specific container using the appropriate command.
func restartContainer(container string) error { func restartContainer(container string) error {
fmt.Println("Restarting containers...") fmt.Println("Restarting containers...")
if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "restart", container); err != nil { if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "restart", container); err != nil {
return fmt.Errorf("failed to stop the container \"%s\": %v", container, err) return fmt.Errorf("failed to stop the container \"%s\": %v", container, err)
} }

View file

@ -37,7 +37,7 @@
"name": "Name", "name": "Name",
"online": "Online", "online": "Online",
"offline": "Offline", "offline": "Offline",
"site": "Site", "site": "Seite",
"dataIn": "Daten eingehend", "dataIn": "Daten eingehend",
"dataOut": "Daten ausgehend", "dataOut": "Daten ausgehend",
"connectionType": "Verbindungstyp", "connectionType": "Verbindungstyp",
@ -114,7 +114,7 @@
"shareTokenDescription": "Ihr Zugriffstoken kann auf zwei Arten übergeben werden: als Abfrageparameter oder in den Anfrage-Headern. Diese müssen vom Client auf jeder Anfrage für authentifizierten Zugriff weitergegeben werden.", "shareTokenDescription": "Ihr Zugriffstoken kann auf zwei Arten übergeben werden: als Abfrageparameter oder in den Anfrage-Headern. Diese müssen vom Client auf jeder Anfrage für authentifizierten Zugriff weitergegeben werden.",
"accessToken": "Zugangs-Token", "accessToken": "Zugangs-Token",
"usageExamples": "Nutzungsbeispiele", "usageExamples": "Nutzungsbeispiele",
"tokenId": "Token ID", "tokenId": "Token-ID",
"requestHeades": "Anfrage-Header", "requestHeades": "Anfrage-Header",
"queryParameter": "Abfrageparameter", "queryParameter": "Abfrageparameter",
"importantNote": "Wichtige Notiz", "importantNote": "Wichtige Notiz",
@ -177,8 +177,8 @@
"subdomnainDescription": "Die Subdomäne, auf die Ihre Ressource zugegriffen werden soll.", "subdomnainDescription": "Die Subdomäne, auf die Ihre Ressource zugegriffen werden soll.",
"resourceRawSettings": "TCP/UDP Einstellungen", "resourceRawSettings": "TCP/UDP Einstellungen",
"resourceRawSettingsDescription": "Konfigurieren Sie den Zugriff auf Ihre Ressource über TCP/UDP", "resourceRawSettingsDescription": "Konfigurieren Sie den Zugriff auf Ihre Ressource über TCP/UDP",
"protocol": "Protocol", "protocol": "Protokoll",
"protocolSelect": "Select a protocol", "protocolSelect": "Wählen Sie ein Protokoll",
"resourcePortNumber": "Portnummer", "resourcePortNumber": "Portnummer",
"resourcePortNumberDescription": "Die externe Portnummer für Proxy-Anfragen.", "resourcePortNumberDescription": "Die externe Portnummer für Proxy-Anfragen.",
"cancel": "Abbrechen", "cancel": "Abbrechen",
@ -300,7 +300,7 @@
"userMessageConfirm": "Um zu bestätigen, geben Sie bitte den Namen des Benutzers unten ein.", "userMessageConfirm": "Um zu bestätigen, geben Sie bitte den Namen des Benutzers unten ein.",
"userQuestionRemove": "Sind Sie sicher, dass Sie {selectedUser} dauerhaft vom Server löschen möchten?", "userQuestionRemove": "Sind Sie sicher, dass Sie {selectedUser} dauerhaft vom Server löschen möchten?",
"licenseKey": "Lizenzschlüssel", "licenseKey": "Lizenzschlüssel",
"valid": "Valid", "valid": "Gültig",
"numberOfSites": "Anzahl der Sites", "numberOfSites": "Anzahl der Sites",
"licenseKeySearch": "Lizenzschlüssel suchen...", "licenseKeySearch": "Lizenzschlüssel suchen...",
"licenseKeyAdd": "Lizenzschlüssel hinzufügen", "licenseKeyAdd": "Lizenzschlüssel hinzufügen",
@ -700,7 +700,7 @@
"accessRoleRequiredRemove": "Bevor Sie diese Rolle löschen, wählen Sie bitte eine neue Rolle aus, zu der die bestehenden Mitglieder übertragen werden sollen.", "accessRoleRequiredRemove": "Bevor Sie diese Rolle löschen, wählen Sie bitte eine neue Rolle aus, zu der die bestehenden Mitglieder übertragen werden sollen.",
"manage": "Verwalten", "manage": "Verwalten",
"sitesNotFound": "Keine Sites gefunden.", "sitesNotFound": "Keine Sites gefunden.",
"pangolinServerAdmin": "Server Admin - Pangolin", "pangolinServerAdmin": "Server-Admin - Pangolin",
"licenseTierProfessional": "Professional Lizenz", "licenseTierProfessional": "Professional Lizenz",
"licenseTierEnterprise": "Enterprise Lizenz", "licenseTierEnterprise": "Enterprise Lizenz",
"licenseTierCommercial": "Gewerbliche Lizenz", "licenseTierCommercial": "Gewerbliche Lizenz",
@ -805,7 +805,7 @@
"redirectUrl": "Weiterleitungs-URL", "redirectUrl": "Weiterleitungs-URL",
"redirectUrlAbout": "Über die Weiterleitungs-URL", "redirectUrlAbout": "Über die Weiterleitungs-URL",
"redirectUrlAboutDescription": "Dies ist die URL, zu der Benutzer nach der Authentifizierung weitergeleitet werden. Sie müssen diese URL in den Einstellungen Ihres Identitätsanbieters konfigurieren.", "redirectUrlAboutDescription": "Dies ist die URL, zu der Benutzer nach der Authentifizierung weitergeleitet werden. Sie müssen diese URL in den Einstellungen Ihres Identitätsanbieters konfigurieren.",
"pangolinAuth": "Auth - Pangolin", "pangolinAuth": "Authentifizierung - Pangolin",
"verificationCodeLengthRequirements": "Ihr Verifizierungscode muss 8 Zeichen lang sein.", "verificationCodeLengthRequirements": "Ihr Verifizierungscode muss 8 Zeichen lang sein.",
"errorOccurred": "Ein Fehler ist aufgetreten", "errorOccurred": "Ein Fehler ist aufgetreten",
"emailErrorVerify": "E-Mail konnte nicht verifiziert werden:", "emailErrorVerify": "E-Mail konnte nicht verifiziert werden:",
@ -1104,7 +1104,7 @@
"containerLabels": "Etiketten", "containerLabels": "Etiketten",
"containerLabelsCount": "{count} Label{s,plural,one{} other{s}}", "containerLabelsCount": "{count} Label{s,plural,one{} other{s}}",
"containerLabelsTitle": "Container-Labels", "containerLabelsTitle": "Container-Labels",
"containerLabelEmpty": "<empty>", "containerLabelEmpty": "<leer>",
"containerPorts": "Häfen", "containerPorts": "Häfen",
"containerPortsMore": "+{count} mehr", "containerPortsMore": "+{count} mehr",
"containerActions": "Aktionen", "containerActions": "Aktionen",
@ -1127,6 +1127,10 @@
"noContainersFoundMatching": "Keine Container gefunden mit \"{filter}\".", "noContainersFoundMatching": "Keine Container gefunden mit \"{filter}\".",
"light": "hell", "light": "hell",
"dark": "dunkel", "dark": "dunkel",
"system": "system", "system": "System",
"theme": "Design" "theme": "Design",
} "initialSetupTitle": "Initial Einrichtung des Servers",
"initialSetupDescription": "Erstellen Sie das initiale Server-Admin-Konto. Es kann nur einen Server-Admin geben. Sie können diese Anmeldedaten später immer ändern.",
"createAdminAccount": "Admin-Konto erstellen",
"setupErrorCreateAdmin": "Beim Erstellen des Server-Admin-Kontos ist ein Fehler aufgetreten."
}

View file

@ -114,7 +114,7 @@
"shareTokenDescription": "Su token de acceso puede ser pasado de dos maneras: como parámetro de consulta o en las cabeceras de solicitud. Estos deben ser pasados del cliente en cada solicitud de acceso autenticado.", "shareTokenDescription": "Su token de acceso puede ser pasado de dos maneras: como parámetro de consulta o en las cabeceras de solicitud. Estos deben ser pasados del cliente en cada solicitud de acceso autenticado.",
"accessToken": "Token de acceso", "accessToken": "Token de acceso",
"usageExamples": "Ejemplos de uso", "usageExamples": "Ejemplos de uso",
"tokenId": "Token ID", "tokenId": "ID de token",
"requestHeades": "Solicitar cabeceras", "requestHeades": "Solicitar cabeceras",
"queryParameter": "Parámetro de consulta", "queryParameter": "Parámetro de consulta",
"importantNote": "Nota Importante", "importantNote": "Nota Importante",
@ -177,8 +177,8 @@
"subdomnainDescription": "El subdominio al que su recurso será accesible.", "subdomnainDescription": "El subdominio al que su recurso será accesible.",
"resourceRawSettings": "Configuración TCP/UDP", "resourceRawSettings": "Configuración TCP/UDP",
"resourceRawSettingsDescription": "Configurar cómo se accederá a su recurso a través de TCP/UDP", "resourceRawSettingsDescription": "Configurar cómo se accederá a su recurso a través de TCP/UDP",
"protocol": "Protocol", "protocol": "Protocolo",
"protocolSelect": "Select a protocol", "protocolSelect": "Seleccionar un protocolo",
"resourcePortNumber": "Número de puerto", "resourcePortNumber": "Número de puerto",
"resourcePortNumberDescription": "El número de puerto externo a las solicitudes de proxy.", "resourcePortNumberDescription": "El número de puerto externo a las solicitudes de proxy.",
"cancel": "Cancelar", "cancel": "Cancelar",
@ -300,7 +300,7 @@
"userMessageConfirm": "Para confirmar, por favor escriba el nombre del usuario a continuación.", "userMessageConfirm": "Para confirmar, por favor escriba el nombre del usuario a continuación.",
"userQuestionRemove": "¿Está seguro que desea eliminar permanentemente {selectedUser} del servidor?", "userQuestionRemove": "¿Está seguro que desea eliminar permanentemente {selectedUser} del servidor?",
"licenseKey": "Clave de licencia", "licenseKey": "Clave de licencia",
"valid": "Valid", "valid": "Válido",
"numberOfSites": "Número de sitios", "numberOfSites": "Número de sitios",
"licenseKeySearch": "Buscar claves de licencia...", "licenseKeySearch": "Buscar claves de licencia...",
"licenseKeyAdd": "Añadir clave de licencia", "licenseKeyAdd": "Añadir clave de licencia",
@ -373,7 +373,7 @@
"inviteSent": "Se ha enviado una nueva invitación a {email}.", "inviteSent": "Se ha enviado una nueva invitación a {email}.",
"inviteSentEmail": "Enviar notificación por correo electrónico al usuario", "inviteSentEmail": "Enviar notificación por correo electrónico al usuario",
"inviteGenerate": "Se ha generado una nueva invitación para {email}.", "inviteGenerate": "Se ha generado una nueva invitación para {email}.",
"inviteDuplicateError": "Duplicate Invite", "inviteDuplicateError": "Invitación duplicada",
"inviteDuplicateErrorDescription": "Ya existe una invitación para este usuario.", "inviteDuplicateErrorDescription": "Ya existe una invitación para este usuario.",
"inviteRateLimitError": "Límite de tasa excedido", "inviteRateLimitError": "Límite de tasa excedido",
"inviteRateLimitErrorDescription": "Has superado el límite de 3 regeneraciones por hora. Inténtalo de nuevo más tarde.", "inviteRateLimitErrorDescription": "Has superado el límite de 3 regeneraciones por hora. Inténtalo de nuevo más tarde.",
@ -463,9 +463,9 @@
"targetErrorFetchDescription": "Se ha producido un error al recuperar los objetivos", "targetErrorFetchDescription": "Se ha producido un error al recuperar los objetivos",
"siteErrorFetch": "No se pudo obtener el recurso", "siteErrorFetch": "No se pudo obtener el recurso",
"siteErrorFetchDescription": "Se ha producido un error al recuperar el recurso", "siteErrorFetchDescription": "Se ha producido un error al recuperar el recurso",
"targetErrorDuplicate": "Duplicate target", "targetErrorDuplicate": "Objetivo duplicado",
"targetErrorDuplicateDescription": "Ya existe un objetivo con estos ajustes", "targetErrorDuplicateDescription": "Ya existe un objetivo con estos ajustes",
"targetWireGuardErrorInvalidIp": "Invalid target IP", "targetWireGuardErrorInvalidIp": "IP de destino no válida",
"targetWireGuardErrorInvalidIpDescription": "La IP de destino debe estar dentro de la subred del sitio", "targetWireGuardErrorInvalidIpDescription": "La IP de destino debe estar dentro de la subred del sitio",
"targetsUpdated": "Objetivos actualizados", "targetsUpdated": "Objetivos actualizados",
"targetsUpdatedDescription": "Objetivos y ajustes actualizados correctamente", "targetsUpdatedDescription": "Objetivos y ajustes actualizados correctamente",
@ -479,9 +479,9 @@
"proxyUpdatedDescription": "La configuración del proxy se ha actualizado correctamente", "proxyUpdatedDescription": "La configuración del proxy se ha actualizado correctamente",
"proxyErrorUpdate": "Error al actualizar la configuración del proxy", "proxyErrorUpdate": "Error al actualizar la configuración del proxy",
"proxyErrorUpdateDescription": "Se ha producido un error al actualizar la configuración del proxy", "proxyErrorUpdateDescription": "Se ha producido un error al actualizar la configuración del proxy",
"targetAddr": "IP / Hostname", "targetAddr": "IP / Nombre del host",
"targetPort": "Puerto", "targetPort": "Puerto",
"targetProtocol": "Protocol", "targetProtocol": "Protocolo",
"targetTlsSettings": "Configuración de conexión segura", "targetTlsSettings": "Configuración de conexión segura",
"targetTlsSettingsDescription": "Configurar ajustes SSL/TLS para su recurso", "targetTlsSettingsDescription": "Configurar ajustes SSL/TLS para su recurso",
"targetTlsSettingsAdvanced": "Ajustes avanzados de TLS", "targetTlsSettingsAdvanced": "Ajustes avanzados de TLS",
@ -493,7 +493,7 @@
"targetStickySessions": "Activar Sesiones Pegadas", "targetStickySessions": "Activar Sesiones Pegadas",
"targetStickySessionsDescription": "Mantener conexiones en el mismo objetivo de backend para toda su sesión.", "targetStickySessionsDescription": "Mantener conexiones en el mismo objetivo de backend para toda su sesión.",
"methodSelect": "Seleccionar método", "methodSelect": "Seleccionar método",
"targetSubmit": "Add Target", "targetSubmit": "Añadir destino",
"targetNoOne": "No hay objetivos. Agregue un objetivo usando el formulario.", "targetNoOne": "No hay objetivos. Agregue un objetivo usando el formulario.",
"targetNoOneDescription": "Si se añade más de un objetivo anterior se activará el balance de carga.", "targetNoOneDescription": "Si se añade más de un objetivo anterior se activará el balance de carga.",
"targetsSubmit": "Guardar objetivos", "targetsSubmit": "Guardar objetivos",
@ -585,8 +585,8 @@
"unknownCommand": "Comando desconocido", "unknownCommand": "Comando desconocido",
"newtErrorFetchReleases": "No se pudo obtener la información del lanzamiento: {err}", "newtErrorFetchReleases": "No se pudo obtener la información del lanzamiento: {err}",
"newtErrorFetchLatest": "Error obteniendo la última versión: {err}", "newtErrorFetchLatest": "Error obteniendo la última versión: {err}",
"newtEndpoint": "Newt Endpoint", "newtEndpoint": "Punto final de Newt",
"newtId": "Newt ID", "newtId": "ID de Newt",
"newtSecretKey": "Clave secreta de Newt", "newtSecretKey": "Clave secreta de Newt",
"architecture": "Arquitectura", "architecture": "Arquitectura",
"sites": "Sitios", "sites": "Sitios",
@ -867,7 +867,7 @@
"passwordReset": "Restablecer contraseña", "passwordReset": "Restablecer contraseña",
"passwordResetDescription": "Siga los pasos para restablecer su contraseña", "passwordResetDescription": "Siga los pasos para restablecer su contraseña",
"passwordResetSent": "Enviaremos un código para restablecer la contraseña a esta dirección de correo electrónico.", "passwordResetSent": "Enviaremos un código para restablecer la contraseña a esta dirección de correo electrónico.",
"passwordResetCode": "Reset Code", "passwordResetCode": "Código de restablecimiento",
"passwordResetCodeDescription": "Revisa tu correo electrónico para ver el código de restablecimiento.", "passwordResetCodeDescription": "Revisa tu correo electrónico para ver el código de restablecimiento.",
"passwordNew": "Nueva contraseña", "passwordNew": "Nueva contraseña",
"passwordNewConfirm": "Confirmar nueva contraseña", "passwordNewConfirm": "Confirmar nueva contraseña",
@ -895,7 +895,7 @@
"inviteErrorExpired": "La invitación puede haber caducado", "inviteErrorExpired": "La invitación puede haber caducado",
"inviteErrorRevoked": "La invitación podría haber sido revocada", "inviteErrorRevoked": "La invitación podría haber sido revocada",
"inviteErrorTypo": "Puede haber un error en el enlace de invitación", "inviteErrorTypo": "Puede haber un error en el enlace de invitación",
"pangolinSetup": "Setup - Pangolin", "pangolinSetup": "Configuración - Pangolin",
"orgNameRequired": "El nombre de la organización es obligatorio", "orgNameRequired": "El nombre de la organización es obligatorio",
"orgIdRequired": "El ID de la organización es obligatorio", "orgIdRequired": "El ID de la organización es obligatorio",
"orgErrorCreate": "Se ha producido un error al crear el org", "orgErrorCreate": "Se ha producido un error al crear el org",
@ -923,7 +923,7 @@
"tagWarnDuplicate": "Etiqueta {tagText} duplicada no añadida", "tagWarnDuplicate": "Etiqueta {tagText} duplicada no añadida",
"supportKeyInvalid": "Clave inválida", "supportKeyInvalid": "Clave inválida",
"supportKeyInvalidDescription": "Tu clave de seguidor no es válida.", "supportKeyInvalidDescription": "Tu clave de seguidor no es válida.",
"supportKeyValid": "Valid Key", "supportKeyValid": "Clave válida",
"supportKeyValidDescription": "Su clave de seguidor ha sido validada. ¡Gracias por su apoyo!", "supportKeyValidDescription": "Su clave de seguidor ha sido validada. ¡Gracias por su apoyo!",
"supportKeyErrorValidationDescription": "Error al validar la clave de seguidor.", "supportKeyErrorValidationDescription": "Error al validar la clave de seguidor.",
"supportKey": "¡Apoya el Desarrollo y Adopte un Pangolin!", "supportKey": "¡Apoya el Desarrollo y Adopte un Pangolin!",
@ -945,7 +945,7 @@
"supportKeyHideSevenDays": "Ocultar durante 7 días", "supportKeyHideSevenDays": "Ocultar durante 7 días",
"supportKeyEnter": "Introduzca Clave de Soporter", "supportKeyEnter": "Introduzca Clave de Soporter",
"supportKeyEnterDescription": "Conoce a tu propia mascota Pangolin!", "supportKeyEnterDescription": "Conoce a tu propia mascota Pangolin!",
"githubUsername": "GitHub Username", "githubUsername": "Nombre de usuario de GitHub",
"supportKeyInput": "Clave de apoyo", "supportKeyInput": "Clave de apoyo",
"supportKeyBuy": "Comprar Clave de Apoyo", "supportKeyBuy": "Comprar Clave de Apoyo",
"logoutError": "Error al cerrar sesión", "logoutError": "Error al cerrar sesión",
@ -979,11 +979,11 @@
"actionSetResourcePincode": "Establecer Pincode del recurso", "actionSetResourcePincode": "Establecer Pincode del recurso",
"actionSetResourceEmailWhitelist": "Establecer lista blanca de correo de recursos", "actionSetResourceEmailWhitelist": "Establecer lista blanca de correo de recursos",
"actionGetResourceEmailWhitelist": "Obtener correo electrónico de recursos", "actionGetResourceEmailWhitelist": "Obtener correo electrónico de recursos",
"actionCreateTarget": "Create Target", "actionCreateTarget": "Crear destino",
"actionDeleteTarget": "Eliminar destino", "actionDeleteTarget": "Eliminar destino",
"actionGetTarget": "Obtener objetivo", "actionGetTarget": "Obtener objetivo",
"actionListTargets": "Lista de objetivos", "actionListTargets": "Lista de objetivos",
"actionUpdateTarget": "Update Target", "actionUpdateTarget": "Actualizar destino",
"actionCreateRole": "Crear rol", "actionCreateRole": "Crear rol",
"actionDeleteRole": "Eliminar rol", "actionDeleteRole": "Eliminar rol",
"actionGetRole": "Obtener rol", "actionGetRole": "Obtener rol",
@ -1031,7 +1031,7 @@
"otpAuthSubmit": "Enviar código", "otpAuthSubmit": "Enviar código",
"idpContinue": "O continuar con", "idpContinue": "O continuar con",
"otpAuthBack": "Volver a iniciar sesión", "otpAuthBack": "Volver a iniciar sesión",
"navbar": "Navigation Menu", "navbar": "Menú de navegación",
"navbarDescription": "Menú de navegación principal para la aplicación", "navbarDescription": "Menú de navegación principal para la aplicación",
"navbarDocsLink": "Documentación", "navbarDocsLink": "Documentación",
"commercialEdition": "Edición Comercial", "commercialEdition": "Edición Comercial",
@ -1100,11 +1100,11 @@
"containerImage": "Imagen", "containerImage": "Imagen",
"containerState": "Estado", "containerState": "Estado",
"containerNetworks": "Redes", "containerNetworks": "Redes",
"containerHostnameIp": "Hostname/IP", "containerHostnameIp": "Nombre del host/IP",
"containerLabels": "Etiquetas", "containerLabels": "Etiquetas",
"containerLabelsCount": "{count} etiqueta{s,plural,one{} other{s}}", "containerLabelsCount": "{count} etiqueta{s,plural,one{} other{s}}",
"containerLabelsTitle": "Etiquetas de contenedor", "containerLabelsTitle": "Etiquetas de contenedor",
"containerLabelEmpty": "<empty>", "containerLabelEmpty": "<vacío>",
"containerPorts": "Puertos", "containerPorts": "Puertos",
"containerPortsMore": "+{count} más", "containerPortsMore": "+{count} más",
"containerActions": "Acciones", "containerActions": "Acciones",
@ -1128,5 +1128,9 @@
"light": "claro", "light": "claro",
"dark": "oscuro", "dark": "oscuro",
"system": "sistema", "system": "sistema",
"theme": "Tema" "theme": "Tema",
} "initialSetupTitle": "Configuración inicial del servidor",
"initialSetupDescription": "Cree la cuenta de administrador del servidor inicial. Solo puede existir un administrador del servidor. Siempre puede cambiar estas credenciales más tarde.",
"createAdminAccount": "Crear cuenta de administrador",
"setupErrorCreateAdmin": "Se produjo un error al crear la cuenta de administrador del servidor."
}

View file

@ -114,7 +114,7 @@
"shareTokenDescription": "Votre jeton d'accès peut être passé de deux façons : en tant que paramètre de requête ou dans les en-têtes de la requête. Elles doivent être transmises par le client à chaque demande d'accès authentifié.", "shareTokenDescription": "Votre jeton d'accès peut être passé de deux façons : en tant que paramètre de requête ou dans les en-têtes de la requête. Elles doivent être transmises par le client à chaque demande d'accès authentifié.",
"accessToken": "Jeton d'accès", "accessToken": "Jeton d'accès",
"usageExamples": "Exemples d'utilisation", "usageExamples": "Exemples d'utilisation",
"tokenId": "Token ID", "tokenId": "ID du jeton",
"requestHeades": "En-têtes de la requête", "requestHeades": "En-têtes de la requête",
"queryParameter": "Paramètre de requête", "queryParameter": "Paramètre de requête",
"importantNote": "Note importante", "importantNote": "Note importante",
@ -177,8 +177,8 @@
"subdomnainDescription": "Le sous-domaine où votre ressource sera accessible.", "subdomnainDescription": "Le sous-domaine où votre ressource sera accessible.",
"resourceRawSettings": "Paramètres TCP/UDP", "resourceRawSettings": "Paramètres TCP/UDP",
"resourceRawSettingsDescription": "Configurer comment votre ressource sera accédée via TCP/UDP", "resourceRawSettingsDescription": "Configurer comment votre ressource sera accédée via TCP/UDP",
"protocol": "Protocol", "protocol": "Protocole",
"protocolSelect": "Select a protocol", "protocolSelect": "Sélectionner un protocole",
"resourcePortNumber": "Numéro de port", "resourcePortNumber": "Numéro de port",
"resourcePortNumberDescription": "Le numéro de port externe pour les requêtes de proxy.", "resourcePortNumberDescription": "Le numéro de port externe pour les requêtes de proxy.",
"cancel": "Abandonner", "cancel": "Abandonner",
@ -300,7 +300,7 @@
"userMessageConfirm": "Pour confirmer, veuillez saisir le nom de l'utilisateur ci-dessous.", "userMessageConfirm": "Pour confirmer, veuillez saisir le nom de l'utilisateur ci-dessous.",
"userQuestionRemove": "Êtes-vous sûr de vouloir supprimer définitivement {selectedUser} du serveur?", "userQuestionRemove": "Êtes-vous sûr de vouloir supprimer définitivement {selectedUser} du serveur?",
"licenseKey": "Clé de licence", "licenseKey": "Clé de licence",
"valid": "Valid", "valid": "Valide",
"numberOfSites": "Nombre de sites", "numberOfSites": "Nombre de sites",
"licenseKeySearch": "Rechercher des clés de licence...", "licenseKeySearch": "Rechercher des clés de licence...",
"licenseKeyAdd": "Ajouter une clé de licence", "licenseKeyAdd": "Ajouter une clé de licence",
@ -1100,11 +1100,11 @@
"containerImage": "Image", "containerImage": "Image",
"containerState": "État", "containerState": "État",
"containerNetworks": "Réseaux", "containerNetworks": "Réseaux",
"containerHostnameIp": "Hostname/IP", "containerHostnameIp": "Nom d'hôte/IP",
"containerLabels": "Étiquettes", "containerLabels": "Étiquettes",
"containerLabelsCount": "{count} label{s,plural,one{} other{s}}", "containerLabelsCount": "{count} étiquette{s,plural,one{} other{s}}",
"containerLabelsTitle": "Étiquettes de conteneur", "containerLabelsTitle": "Étiquettes de conteneur",
"containerLabelEmpty": "<empty>", "containerLabelEmpty": "<vide>",
"containerPorts": "Ports", "containerPorts": "Ports",
"containerPortsMore": "+{count} de plus", "containerPortsMore": "+{count} de plus",
"containerActions": "Actions", "containerActions": "Actions",
@ -1128,5 +1128,9 @@
"light": "clair", "light": "clair",
"dark": "sombre", "dark": "sombre",
"system": "système", "system": "système",
"theme": "Thème" "theme": "Thème",
} "initialSetupTitle": "Configuration initiale du serveur",
"initialSetupDescription": "Créer le compte administrateur du serveur initial. Un seul administrateur serveur peut exister. Vous pouvez toujours changer ces informations d'identification plus tard.",
"createAdminAccount": "Créer un compte administrateur",
"setupErrorCreateAdmin": "Une erreur s'est produite lors de la création du compte administrateur du serveur."
}

View file

@ -73,7 +73,7 @@
"searchSitesProgress": "Cerca siti...", "searchSitesProgress": "Cerca siti...",
"siteAdd": "Aggiungi Sito", "siteAdd": "Aggiungi Sito",
"siteInstallNewt": "Installa Newt", "siteInstallNewt": "Installa Newt",
"siteInstallNewtDescription": "Get Newt running on your system", "siteInstallNewtDescription": "Esegui Newt sul tuo sistema",
"WgConfiguration": "Configurazione WireGuard", "WgConfiguration": "Configurazione WireGuard",
"WgConfigurationDescription": "Usa la seguente configurazione per connetterti alla tua rete", "WgConfigurationDescription": "Usa la seguente configurazione per connetterti alla tua rete",
"operatingSystem": "Sistema Operativo", "operatingSystem": "Sistema Operativo",
@ -114,7 +114,7 @@
"shareTokenDescription": "Il token di accesso può essere passato in due modi: come parametro di interrogazione o nelle intestazioni della richiesta. Questi devono essere passati dal client su ogni richiesta di accesso autenticato.", "shareTokenDescription": "Il token di accesso può essere passato in due modi: come parametro di interrogazione o nelle intestazioni della richiesta. Questi devono essere passati dal client su ogni richiesta di accesso autenticato.",
"accessToken": "Token Di Accesso", "accessToken": "Token Di Accesso",
"usageExamples": "Esempi Di Utilizzo", "usageExamples": "Esempi Di Utilizzo",
"tokenId": "Token ID", "tokenId": "ID del Token",
"requestHeades": "Richiedi Intestazioni", "requestHeades": "Richiedi Intestazioni",
"queryParameter": "Parametro Query", "queryParameter": "Parametro Query",
"importantNote": "Nota Importante", "importantNote": "Nota Importante",
@ -177,8 +177,8 @@
"subdomnainDescription": "Il sottodominio in cui la tua risorsa sarà accessibile.", "subdomnainDescription": "Il sottodominio in cui la tua risorsa sarà accessibile.",
"resourceRawSettings": "Impostazioni TCP/UDP", "resourceRawSettings": "Impostazioni TCP/UDP",
"resourceRawSettingsDescription": "Configura come accedere alla tua risorsa tramite TCP/UDP", "resourceRawSettingsDescription": "Configura come accedere alla tua risorsa tramite TCP/UDP",
"protocol": "Protocol", "protocol": "Protocollo",
"protocolSelect": "Select a protocol", "protocolSelect": "Seleziona un protocollo",
"resourcePortNumber": "Numero Porta", "resourcePortNumber": "Numero Porta",
"resourcePortNumberDescription": "Il numero di porta esterna per le richieste di proxy.", "resourcePortNumberDescription": "Il numero di porta esterna per le richieste di proxy.",
"cancel": "Annulla", "cancel": "Annulla",
@ -230,7 +230,7 @@
"accessUsersSearch": "Cerca utenti...", "accessUsersSearch": "Cerca utenti...",
"accessUserCreate": "Crea Utente", "accessUserCreate": "Crea Utente",
"accessUserRemove": "Rimuovi Utente", "accessUserRemove": "Rimuovi Utente",
"username": "Username", "username": "Nome utente",
"identityProvider": "Provider Di Identità", "identityProvider": "Provider Di Identità",
"role": "Ruolo", "role": "Ruolo",
"nameRequired": "Il nome è obbligatorio", "nameRequired": "Il nome è obbligatorio",
@ -300,7 +300,7 @@
"userMessageConfirm": "Per confermare, digita il nome dell'utente qui sotto.", "userMessageConfirm": "Per confermare, digita il nome dell'utente qui sotto.",
"userQuestionRemove": "Sei sicuro di voler eliminare definitivamente {selectedUser} dal server?", "userQuestionRemove": "Sei sicuro di voler eliminare definitivamente {selectedUser} dal server?",
"licenseKey": "Chiave Di Licenza", "licenseKey": "Chiave Di Licenza",
"valid": "Valid", "valid": "Valido",
"numberOfSites": "Numero di siti", "numberOfSites": "Numero di siti",
"licenseKeySearch": "Cerca chiavi di licenza...", "licenseKeySearch": "Cerca chiavi di licenza...",
"licenseKeyAdd": "Aggiungi Chiave Di Licenza", "licenseKeyAdd": "Aggiungi Chiave Di Licenza",
@ -316,7 +316,7 @@
"licenseErrorKeyActivate": "Attivazione della chiave di licenza non riuscita", "licenseErrorKeyActivate": "Attivazione della chiave di licenza non riuscita",
"licenseErrorKeyActivateDescription": "Si è verificato un errore nell'attivazione della chiave di licenza.", "licenseErrorKeyActivateDescription": "Si è verificato un errore nell'attivazione della chiave di licenza.",
"licenseAbout": "Informazioni Su Licenze", "licenseAbout": "Informazioni Su Licenze",
"communityEdition": "Community Edition", "communityEdition": "Edizione Community",
"licenseAboutDescription": "Questo è per gli utenti aziendali e aziendali che utilizzano Pangolin in un ambiente commerciale. Se stai usando Pangolin per uso personale, puoi ignorare questa sezione.", "licenseAboutDescription": "Questo è per gli utenti aziendali e aziendali che utilizzano Pangolin in un ambiente commerciale. Se stai usando Pangolin per uso personale, puoi ignorare questa sezione.",
"licenseKeyActivated": "Chiave di licenza attivata", "licenseKeyActivated": "Chiave di licenza attivata",
"licenseKeyActivatedDescription": "La chiave di licenza è stata attivata correttamente.", "licenseKeyActivatedDescription": "La chiave di licenza è stata attivata correttamente.",
@ -339,7 +339,7 @@
"licenseHost": "Licenza Host", "licenseHost": "Licenza Host",
"licenseHostDescription": "Gestisci la chiave di licenza principale per l'host.", "licenseHostDescription": "Gestisci la chiave di licenza principale per l'host.",
"licensedNot": "Non Licenziato", "licensedNot": "Non Licenziato",
"hostId": "Host ID", "hostId": "ID Host",
"licenseReckeckAll": "Ricontrolla Tutte Le Tasti", "licenseReckeckAll": "Ricontrolla Tutte Le Tasti",
"licenseSiteUsage": "Utilizzo Siti", "licenseSiteUsage": "Utilizzo Siti",
"licenseSiteUsageDecsription": "Visualizza il numero di siti che utilizzano questa licenza.", "licenseSiteUsageDecsription": "Visualizza il numero di siti che utilizzano questa licenza.",
@ -1104,7 +1104,7 @@
"containerLabels": "Etichette", "containerLabels": "Etichette",
"containerLabelsCount": "{count} etichetta{s,plural,one{} other{s}}", "containerLabelsCount": "{count} etichetta{s,plural,one{} other{s}}",
"containerLabelsTitle": "Etichette Del Contenitore", "containerLabelsTitle": "Etichette Del Contenitore",
"containerLabelEmpty": "<empty>", "containerLabelEmpty": "<vuoto>",
"containerPorts": "Porte", "containerPorts": "Porte",
"containerPortsMore": "+{count} in più", "containerPortsMore": "+{count} in più",
"containerActions": "Azioni", "containerActions": "Azioni",
@ -1128,5 +1128,9 @@
"light": "chiaro", "light": "chiaro",
"dark": "scuro", "dark": "scuro",
"system": "sistema", "system": "sistema",
"theme": "Tema" "theme": "Tema",
} "initialSetupTitle": "Impostazione Iniziale del Server",
"initialSetupDescription": "Crea l'account amministratore del server iniziale. Può esistere solo un amministratore del server. È sempre possibile modificare queste credenziali in seguito.",
"createAdminAccount": "Crea Account Admin",
"setupErrorCreateAdmin": "Si è verificato un errore durante la creazione dell'account amministratore del server."
}

View file

@ -12,7 +12,7 @@
"componentsErrorNoMember": "U bent momenteel geen lid van een organisatie.", "componentsErrorNoMember": "U bent momenteel geen lid van een organisatie.",
"welcome": "Welkom bij Pangolin", "welcome": "Welkom bij Pangolin",
"componentsCreateOrg": "Maak een Organisatie", "componentsCreateOrg": "Maak een Organisatie",
"componentsMember": "You're a member of {count, plural, =0 {no organization} =1 {one organization} other {# organizations}}.", "componentsMember": "Je bent lid van {count, plural, =0 {geen organisatie} =1 {één organisatie} other {# organisaties}}.",
"componentsInvalidKey": "Ongeldige of verlopen licentiesleutels gedetecteerd. Volg de licentievoorwaarden om alle functies te blijven gebruiken.", "componentsInvalidKey": "Ongeldige of verlopen licentiesleutels gedetecteerd. Volg de licentievoorwaarden om alle functies te blijven gebruiken.",
"dismiss": "Uitschakelen", "dismiss": "Uitschakelen",
"componentsLicenseViolation": "Licentie overtreding: Deze server gebruikt {usedSites} sites die de gelicentieerde limiet van {maxSites} sites overschrijden. Volg de licentievoorwaarden om door te gaan met het gebruik van alle functies.", "componentsLicenseViolation": "Licentie overtreding: Deze server gebruikt {usedSites} sites die de gelicentieerde limiet van {maxSites} sites overschrijden. Volg de licentievoorwaarden om door te gaan met het gebruik van alle functies.",
@ -92,7 +92,7 @@
"siteSetting": "{siteName} instellingen", "siteSetting": "{siteName} instellingen",
"siteNewtTunnel": "Nieuwstunnel (Aanbevolen)", "siteNewtTunnel": "Nieuwstunnel (Aanbevolen)",
"siteNewtTunnelDescription": "Gemakkelijkste manier om een ingangspunt in uw netwerk te maken. Geen extra opzet.", "siteNewtTunnelDescription": "Gemakkelijkste manier om een ingangspunt in uw netwerk te maken. Geen extra opzet.",
"siteWg": "Basic WireGuard", "siteWg": "Basis WireGuard",
"siteWgDescription": "Gebruik een WireGuard client om een tunnel te bouwen. Handmatige NAT installatie vereist.", "siteWgDescription": "Gebruik een WireGuard client om een tunnel te bouwen. Handmatige NAT installatie vereist.",
"siteLocalDescription": "Alleen lokale bronnen. Geen tunneling.", "siteLocalDescription": "Alleen lokale bronnen. Geen tunneling.",
"siteSeeAll": "Alle werkruimtes bekijken", "siteSeeAll": "Alle werkruimtes bekijken",
@ -116,7 +116,7 @@
"usageExamples": "Voorbeelden van gebruik", "usageExamples": "Voorbeelden van gebruik",
"tokenId": "Token ID", "tokenId": "Token ID",
"requestHeades": "Aanvraag van headers", "requestHeades": "Aanvraag van headers",
"queryParameter": "Query Parameter", "queryParameter": "Queryparameter",
"importantNote": "Belangrijke opmerking", "importantNote": "Belangrijke opmerking",
"shareImportantDescription": "Om veiligheidsredenen wordt het gebruik van headers aanbevolen over queryparameters indien mogelijk, omdat query parameters kunnen worden aangemeld in serverlogboeken of browsergeschiedenis.", "shareImportantDescription": "Om veiligheidsredenen wordt het gebruik van headers aanbevolen over queryparameters indien mogelijk, omdat query parameters kunnen worden aangemeld in serverlogboeken of browsergeschiedenis.",
"token": "Token", "token": "Token",
@ -178,7 +178,7 @@
"resourceRawSettings": "TCP/UDP instellingen", "resourceRawSettings": "TCP/UDP instellingen",
"resourceRawSettingsDescription": "Stel in hoe je bron wordt benaderd via TCP/UDP", "resourceRawSettingsDescription": "Stel in hoe je bron wordt benaderd via TCP/UDP",
"protocol": "Protocol", "protocol": "Protocol",
"protocolSelect": "Select a protocol", "protocolSelect": "Selecteer een protocol",
"resourcePortNumber": "Nummer van poort", "resourcePortNumber": "Nummer van poort",
"resourcePortNumberDescription": "Het externe poortnummer naar proxyverzoeken.", "resourcePortNumberDescription": "Het externe poortnummer naar proxyverzoeken.",
"cancel": "annuleren", "cancel": "annuleren",
@ -300,7 +300,7 @@
"userMessageConfirm": "Typ de naam van de gebruiker hieronder om te bevestigen.", "userMessageConfirm": "Typ de naam van de gebruiker hieronder om te bevestigen.",
"userQuestionRemove": "Weet je zeker dat je {selectedUser} permanent van de server wilt verwijderen?", "userQuestionRemove": "Weet je zeker dat je {selectedUser} permanent van de server wilt verwijderen?",
"licenseKey": "Licentie sleutel", "licenseKey": "Licentie sleutel",
"valid": "Valid", "valid": "Geldig",
"numberOfSites": "Aantal sites", "numberOfSites": "Aantal sites",
"licenseKeySearch": "Licentiesleutels zoeken...", "licenseKeySearch": "Licentiesleutels zoeken...",
"licenseKeyAdd": "Licentiesleutel toevoegen", "licenseKeyAdd": "Licentiesleutel toevoegen",
@ -339,7 +339,7 @@
"licenseHost": "Host Licentie", "licenseHost": "Host Licentie",
"licenseHostDescription": "Beheer de belangrijkste licentiesleutel voor de host.", "licenseHostDescription": "Beheer de belangrijkste licentiesleutel voor de host.",
"licensedNot": "Niet gelicentieerd", "licensedNot": "Niet gelicentieerd",
"hostId": "Host ID", "hostId": "Host-ID",
"licenseReckeckAll": "Alle sleutels opnieuw selecteren", "licenseReckeckAll": "Alle sleutels opnieuw selecteren",
"licenseSiteUsage": "Websites gebruik", "licenseSiteUsage": "Websites gebruik",
"licenseSiteUsageDecsription": "Bekijk het aantal sites dat deze licentie gebruikt.", "licenseSiteUsageDecsription": "Bekijk het aantal sites dat deze licentie gebruikt.",
@ -373,7 +373,7 @@
"inviteSent": "Een nieuwe uitnodiging is verstuurd naar {email}.", "inviteSent": "Een nieuwe uitnodiging is verstuurd naar {email}.",
"inviteSentEmail": "Stuur e-mail notificatie naar de gebruiker", "inviteSentEmail": "Stuur e-mail notificatie naar de gebruiker",
"inviteGenerate": "Er is een nieuwe uitnodiging aangemaakt voor {email}.", "inviteGenerate": "Er is een nieuwe uitnodiging aangemaakt voor {email}.",
"inviteDuplicateError": "Duplicate Invite", "inviteDuplicateError": "Dubbele uitnodiging",
"inviteDuplicateErrorDescription": "Er bestaat al een uitnodiging voor deze gebruiker.", "inviteDuplicateErrorDescription": "Er bestaat al een uitnodiging voor deze gebruiker.",
"inviteRateLimitError": "Tarief limiet overschreden", "inviteRateLimitError": "Tarief limiet overschreden",
"inviteRateLimitErrorDescription": "U hebt de limiet van 3 regeneratie per uur overschreden. Probeer het later opnieuw.", "inviteRateLimitErrorDescription": "U hebt de limiet van 3 regeneratie per uur overschreden. Probeer het later opnieuw.",
@ -436,7 +436,7 @@
"accessRoleSelect": "Selecteer rol", "accessRoleSelect": "Selecteer rol",
"inviteEmailSentDescription": "Een e-mail is verstuurd naar de gebruiker met de link hieronder. Ze moeten toegang krijgen tot de link om de uitnodiging te accepteren.", "inviteEmailSentDescription": "Een e-mail is verstuurd naar de gebruiker met de link hieronder. Ze moeten toegang krijgen tot de link om de uitnodiging te accepteren.",
"inviteSentDescription": "De gebruiker is uitgenodigd. Ze moeten toegang krijgen tot de link hieronder om de uitnodiging te accepteren.", "inviteSentDescription": "De gebruiker is uitgenodigd. Ze moeten toegang krijgen tot de link hieronder om de uitnodiging te accepteren.",
"inviteExpiresIn": "The invite will expire in {days, plural, =1 {# day} other {# days}}.", "inviteExpiresIn": "De uitnodiging vervalt in {days, plural, =1 {# dag} other {# dagen}}.",
"idpTitle": "Identiteit Provider", "idpTitle": "Identiteit Provider",
"idpSelect": "Identiteitsprovider voor de externe gebruiker selecteren", "idpSelect": "Identiteitsprovider voor de externe gebruiker selecteren",
"idpNotConfigured": "Er zijn geen identiteitsproviders geconfigureerd. Configureer een identiteitsprovider voordat u externe gebruikers aanmaakt.", "idpNotConfigured": "Er zijn geen identiteitsproviders geconfigureerd. Configureer een identiteitsprovider voordat u externe gebruikers aanmaakt.",
@ -463,9 +463,9 @@
"targetErrorFetchDescription": "Er is een fout opgetreden bij het ophalen van de objecten", "targetErrorFetchDescription": "Er is een fout opgetreden bij het ophalen van de objecten",
"siteErrorFetch": "Mislukt om resource op te halen", "siteErrorFetch": "Mislukt om resource op te halen",
"siteErrorFetchDescription": "Er is een fout opgetreden tijdens het ophalen van het document", "siteErrorFetchDescription": "Er is een fout opgetreden tijdens het ophalen van het document",
"targetErrorDuplicate": "Duplicate target", "targetErrorDuplicate": "Dubbel doelwit",
"targetErrorDuplicateDescription": "Een doel met deze instellingen bestaat al", "targetErrorDuplicateDescription": "Een doel met deze instellingen bestaat al",
"targetWireGuardErrorInvalidIp": "Invalid target IP", "targetWireGuardErrorInvalidIp": "Ongeldig doel-IP",
"targetWireGuardErrorInvalidIpDescription": "Doel IP moet binnen de site subnet zijn", "targetWireGuardErrorInvalidIpDescription": "Doel IP moet binnen de site subnet zijn",
"targetsUpdated": "Doelstellingen bijgewerkt", "targetsUpdated": "Doelstellingen bijgewerkt",
"targetsUpdatedDescription": "Doelstellingen en instellingen succesvol bijgewerkt", "targetsUpdatedDescription": "Doelstellingen en instellingen succesvol bijgewerkt",
@ -479,7 +479,7 @@
"proxyUpdatedDescription": "Uw proxyinstellingen zijn succesvol bijgewerkt", "proxyUpdatedDescription": "Uw proxyinstellingen zijn succesvol bijgewerkt",
"proxyErrorUpdate": "Bijwerken van proxy-instellingen mislukt", "proxyErrorUpdate": "Bijwerken van proxy-instellingen mislukt",
"proxyErrorUpdateDescription": "Fout opgetreden tijdens het bijwerken van de proxy-instellingen", "proxyErrorUpdateDescription": "Fout opgetreden tijdens het bijwerken van de proxy-instellingen",
"targetAddr": "IP / Hostname", "targetAddr": "IP / Hostnaam",
"targetPort": "Poort", "targetPort": "Poort",
"targetProtocol": "Protocol", "targetProtocol": "Protocol",
"targetTlsSettings": "HTTPS & TLS instellingen", "targetTlsSettings": "HTTPS & TLS instellingen",
@ -493,7 +493,7 @@
"targetStickySessions": "Sticky sessies inschakelen", "targetStickySessions": "Sticky sessies inschakelen",
"targetStickySessionsDescription": "Behoud verbindingen op hetzelfde backend doel voor hun hele sessie.", "targetStickySessionsDescription": "Behoud verbindingen op hetzelfde backend doel voor hun hele sessie.",
"methodSelect": "Selecteer methode", "methodSelect": "Selecteer methode",
"targetSubmit": "Add Target", "targetSubmit": "Doelwit toevoegen",
"targetNoOne": "Geen doelwitten. Voeg een doel toe via het formulier.", "targetNoOne": "Geen doelwitten. Voeg een doel toe via het formulier.",
"targetNoOneDescription": "Het toevoegen van meer dan één doel hierboven zal de load balancering mogelijk maken.", "targetNoOneDescription": "Het toevoegen van meer dan één doel hierboven zal de load balancering mogelijk maken.",
"targetsSubmit": "Doelstellingen opslaan", "targetsSubmit": "Doelstellingen opslaan",
@ -585,8 +585,8 @@
"unknownCommand": "Onbekende opdracht", "unknownCommand": "Onbekende opdracht",
"newtErrorFetchReleases": "Kan release-informatie niet ophalen: {err}", "newtErrorFetchReleases": "Kan release-informatie niet ophalen: {err}",
"newtErrorFetchLatest": "Fout bij ophalen van laatste release: {err}", "newtErrorFetchLatest": "Fout bij ophalen van laatste release: {err}",
"newtEndpoint": "Newt Endpoint", "newtEndpoint": "Newt Eindoordeel",
"newtId": "Newt ID", "newtId": "Newt-ID",
"newtSecretKey": "Nieuwe geheime sleutel", "newtSecretKey": "Nieuwe geheime sleutel",
"architecture": "Architectuur", "architecture": "Architectuur",
"sites": "Werkruimtes", "sites": "Werkruimtes",
@ -639,7 +639,7 @@
"resourcePasswordSetupDescription": "Het wachtwoord voor de bron is succesvol ingesteld", "resourcePasswordSetupDescription": "Het wachtwoord voor de bron is succesvol ingesteld",
"resourcePasswordSetupTitle": "Wachtwoord instellen", "resourcePasswordSetupTitle": "Wachtwoord instellen",
"resourcePasswordSetupTitleDescription": "Stel een wachtwoord in om deze bron te beschermen", "resourcePasswordSetupTitleDescription": "Stel een wachtwoord in om deze bron te beschermen",
"resourcePincode": "PIN Code", "resourcePincode": "Pincode",
"resourcePincodeSubmit": "PIN-Code bescherming inschakelen", "resourcePincodeSubmit": "PIN-Code bescherming inschakelen",
"resourcePincodeProtection": "PIN Code bescherming {status}", "resourcePincodeProtection": "PIN Code bescherming {status}",
"resourcePincodeRemove": "Pijncode van resource verwijderd", "resourcePincodeRemove": "Pijncode van resource verwijderd",
@ -700,7 +700,7 @@
"accessRoleRequiredRemove": "Voordat u deze rol verwijdert, selecteer een nieuwe rol om bestaande leden aan te dragen.", "accessRoleRequiredRemove": "Voordat u deze rol verwijdert, selecteer een nieuwe rol om bestaande leden aan te dragen.",
"manage": "Beheren", "manage": "Beheren",
"sitesNotFound": "Geen sites gevonden.", "sitesNotFound": "Geen sites gevonden.",
"pangolinServerAdmin": "Server Admin - Pangolin", "pangolinServerAdmin": "Serverbeheer - Pangolin",
"licenseTierProfessional": "Professionele licentie", "licenseTierProfessional": "Professionele licentie",
"licenseTierEnterprise": "Enterprise Licentie", "licenseTierEnterprise": "Enterprise Licentie",
"licenseTierCommercial": "Commerciële licentie", "licenseTierCommercial": "Commerciële licentie",
@ -745,7 +745,7 @@
"idpOidcConfigureDescription": "Configureer de eindpunten van de OAuth2/OIDC provider en referenties", "idpOidcConfigureDescription": "Configureer de eindpunten van de OAuth2/OIDC provider en referenties",
"idpClientId": "Klant ID", "idpClientId": "Klant ID",
"idpClientIdDescription": "De OAuth2-client-ID van uw identiteitsprovider", "idpClientIdDescription": "De OAuth2-client-ID van uw identiteitsprovider",
"idpClientSecret": "Client Secret", "idpClientSecret": "Clientgeheim",
"idpClientSecretDescription": "Het OAuth2-clientgeheim van je identiteitsprovider", "idpClientSecretDescription": "Het OAuth2-clientgeheim van je identiteitsprovider",
"idpAuthUrl": "URL autorisatie", "idpAuthUrl": "URL autorisatie",
"idpAuthUrlDescription": "De URL voor autorisatie OAuth2", "idpAuthUrlDescription": "De URL voor autorisatie OAuth2",
@ -826,7 +826,7 @@
"inviteAlready": "Het lijkt erop dat je bent uitgenodigd!", "inviteAlready": "Het lijkt erop dat je bent uitgenodigd!",
"inviteAlreadyDescription": "Om de uitnodiging te accepteren, moet je inloggen of een account aanmaken.", "inviteAlreadyDescription": "Om de uitnodiging te accepteren, moet je inloggen of een account aanmaken.",
"signupQuestion": "Heeft u al een account?", "signupQuestion": "Heeft u al een account?",
"login": "Log in", "login": "Inloggen",
"resourceNotFound": "Bron niet gevonden", "resourceNotFound": "Bron niet gevonden",
"resourceNotFoundDescription": "De bron die u probeert te benaderen bestaat niet.", "resourceNotFoundDescription": "De bron die u probeert te benaderen bestaat niet.",
"pincodeRequirementsLength": "Pincode moet precies 6 cijfers zijn", "pincodeRequirementsLength": "Pincode moet precies 6 cijfers zijn",
@ -867,11 +867,11 @@
"passwordReset": "Wachtwoord opnieuw instellen", "passwordReset": "Wachtwoord opnieuw instellen",
"passwordResetDescription": "Volg de stappen om uw wachtwoord opnieuw in te stellen", "passwordResetDescription": "Volg de stappen om uw wachtwoord opnieuw in te stellen",
"passwordResetSent": "We sturen een wachtwoord reset code naar dit e-mailadres.", "passwordResetSent": "We sturen een wachtwoord reset code naar dit e-mailadres.",
"passwordResetCode": "Reset Code", "passwordResetCode": "Resetcode",
"passwordResetCodeDescription": "Controleer je e-mail voor de reset code.", "passwordResetCodeDescription": "Controleer je e-mail voor de reset code.",
"passwordNew": "Nieuw wachtwoord", "passwordNew": "Nieuw wachtwoord",
"passwordNewConfirm": "Bevestig nieuw wachtwoord", "passwordNewConfirm": "Bevestig nieuw wachtwoord",
"pincodeAuth": "Authenticator Code", "pincodeAuth": "Authenticatiecode",
"pincodeSubmit2": "Code indienen", "pincodeSubmit2": "Code indienen",
"passwordResetSubmit": "Opnieuw instellen aanvragen", "passwordResetSubmit": "Opnieuw instellen aanvragen",
"passwordBack": "Terug naar wachtwoord", "passwordBack": "Terug naar wachtwoord",
@ -923,7 +923,7 @@
"tagWarnDuplicate": "Dubbele tag {tagText} niet toegevoegd", "tagWarnDuplicate": "Dubbele tag {tagText} niet toegevoegd",
"supportKeyInvalid": "Ongeldige sleutel", "supportKeyInvalid": "Ongeldige sleutel",
"supportKeyInvalidDescription": "Je supporter sleutel is ongeldig.", "supportKeyInvalidDescription": "Je supporter sleutel is ongeldig.",
"supportKeyValid": "Valid Key", "supportKeyValid": "Geldige sleutel",
"supportKeyValidDescription": "Uw supporter sleutel is gevalideerd. Bedankt voor uw steun!", "supportKeyValidDescription": "Uw supporter sleutel is gevalideerd. Bedankt voor uw steun!",
"supportKeyErrorValidationDescription": "Niet gelukt om de supportersleutel te valideren.", "supportKeyErrorValidationDescription": "Niet gelukt om de supportersleutel te valideren.",
"supportKey": "Ondersteun ontwikkeling en Adopt een Pangolin!", "supportKey": "Ondersteun ontwikkeling en Adopt een Pangolin!",
@ -945,7 +945,7 @@
"supportKeyHideSevenDays": "Verbergen voor 7 dagen", "supportKeyHideSevenDays": "Verbergen voor 7 dagen",
"supportKeyEnter": "Voer de supportersleutel in", "supportKeyEnter": "Voer de supportersleutel in",
"supportKeyEnterDescription": "Ontmoet je eigen huisdier Pangolin!", "supportKeyEnterDescription": "Ontmoet je eigen huisdier Pangolin!",
"githubUsername": "GitHub Username", "githubUsername": "GitHub-gebruikersnaam",
"supportKeyInput": "Supporter Sleutel", "supportKeyInput": "Supporter Sleutel",
"supportKeyBuy": "Koop Supportersleutel", "supportKeyBuy": "Koop Supportersleutel",
"logoutError": "Fout bij uitloggen", "logoutError": "Fout bij uitloggen",
@ -979,11 +979,11 @@
"actionSetResourcePincode": "Stel Resource Pincode in", "actionSetResourcePincode": "Stel Resource Pincode in",
"actionSetResourceEmailWhitelist": "Stel Resource e-mail whitelist in", "actionSetResourceEmailWhitelist": "Stel Resource e-mail whitelist in",
"actionGetResourceEmailWhitelist": "Verkrijg Resource E-mail Whitelist", "actionGetResourceEmailWhitelist": "Verkrijg Resource E-mail Whitelist",
"actionCreateTarget": "Create Target", "actionCreateTarget": "Doelwit aanmaken",
"actionDeleteTarget": "Verwijder doel", "actionDeleteTarget": "Verwijder doel",
"actionGetTarget": "Verkrijg Doel", "actionGetTarget": "Verkrijg Doel",
"actionListTargets": "Doelstellingen weergeven", "actionListTargets": "Doelstellingen weergeven",
"actionUpdateTarget": "Update Target", "actionUpdateTarget": "Doelwit bijwerken",
"actionCreateRole": "Rol aanmaken", "actionCreateRole": "Rol aanmaken",
"actionDeleteRole": "Verwijder rol", "actionDeleteRole": "Verwijder rol",
"actionGetRole": "Krijg Rol", "actionGetRole": "Krijg Rol",
@ -1018,7 +1018,7 @@
"actionCreateIdpOrg": "Maak IDP Org Policy", "actionCreateIdpOrg": "Maak IDP Org Policy",
"actionDeleteIdpOrg": "Verwijder IDP Org Beleid", "actionDeleteIdpOrg": "Verwijder IDP Org Beleid",
"actionListIdpOrgs": "Toon IDP Orgs", "actionListIdpOrgs": "Toon IDP Orgs",
"actionUpdateIdpOrg": "Update IDP Org", "actionUpdateIdpOrg": "IDP-org bijwerken",
"noneSelected": "Niet geselecteerd", "noneSelected": "Niet geselecteerd",
"orgNotFound2": "Geen organisaties gevonden.", "orgNotFound2": "Geen organisaties gevonden.",
"searchProgress": "Zoeken...", "searchProgress": "Zoeken...",
@ -1031,7 +1031,7 @@
"otpAuthSubmit": "Code indienen", "otpAuthSubmit": "Code indienen",
"idpContinue": "Of ga verder met", "idpContinue": "Of ga verder met",
"otpAuthBack": "Terug naar inloggen", "otpAuthBack": "Terug naar inloggen",
"navbar": "Navigation Menu", "navbar": "Navigatiemenu",
"navbarDescription": "Hoofd navigatie menu voor de applicatie", "navbarDescription": "Hoofd navigatie menu voor de applicatie",
"navbarDocsLink": "Documentatie", "navbarDocsLink": "Documentatie",
"commercialEdition": "Commerciële editie", "commercialEdition": "Commerciële editie",
@ -1042,7 +1042,7 @@
"otpSetup": "Tweestapsverificatie inschakelen", "otpSetup": "Tweestapsverificatie inschakelen",
"otpSetupDescription": "Beveilig je account met een extra beveiligingslaag", "otpSetupDescription": "Beveilig je account met een extra beveiligingslaag",
"otpSetupScanQr": "Scan deze QR-code met je authenticator-app of voer de geheime sleutel handmatig in:", "otpSetupScanQr": "Scan deze QR-code met je authenticator-app of voer de geheime sleutel handmatig in:",
"otpSetupSecretCode": "Authenticator Code", "otpSetupSecretCode": "Authenticatiecode",
"otpSetupSuccess": "Tweestapsverificatie ingeschakeld", "otpSetupSuccess": "Tweestapsverificatie ingeschakeld",
"otpSetupSuccessStoreBackupCodes": "Uw account is nu veiliger. Vergeet niet uw back-upcodes op te slaan.", "otpSetupSuccessStoreBackupCodes": "Uw account is nu veiliger. Vergeet niet uw back-upcodes op te slaan.",
"otpErrorDisable": "Kan 2FA niet uitschakelen", "otpErrorDisable": "Kan 2FA niet uitschakelen",
@ -1100,11 +1100,11 @@
"containerImage": "Afbeelding", "containerImage": "Afbeelding",
"containerState": "Provincie", "containerState": "Provincie",
"containerNetworks": "Netwerken", "containerNetworks": "Netwerken",
"containerHostnameIp": "Hostname/IP", "containerHostnameIp": "Hostnaam/IP",
"containerLabels": "Labels", "containerLabels": "Labels",
"containerLabelsCount": "{count} label{s,plural,one{} other{s}}", "containerLabelsCount": "{count} label{s,plural,one{} other{s}}",
"containerLabelsTitle": "Container labels", "containerLabelsTitle": "Container labels",
"containerLabelEmpty": "<empty>", "containerLabelEmpty": "<leeg>",
"containerPorts": "Poorten", "containerPorts": "Poorten",
"containerPortsMore": "+{count} meer", "containerPortsMore": "+{count} meer",
"containerActions": "acties", "containerActions": "acties",
@ -1128,5 +1128,9 @@
"light": "licht", "light": "licht",
"dark": "donker", "dark": "donker",
"system": "systeem", "system": "systeem",
"theme": "Thema" "theme": "Thema",
} "initialSetupTitle": "Initiële serverconfiguratie",
"initialSetupDescription": "Maak het eerste serverbeheeraccount aan. Er kan slechts één serverbeheerder bestaan. U kunt deze inloggegevens later altijd wijzigen.",
"createAdminAccount": "Maak een beheeraccount aan",
"setupErrorCreateAdmin": "Er is een fout opgetreden bij het maken van het serverbeheerdersaccount."
}

View file

@ -114,7 +114,7 @@
"shareTokenDescription": "Twój token dostępu może być przekazywany na dwa sposoby: jako parametr zapytania lub w nagłówkach żądania. Muszą być przekazywane z klienta na każde żądanie uwierzytelnionego dostępu.", "shareTokenDescription": "Twój token dostępu może być przekazywany na dwa sposoby: jako parametr zapytania lub w nagłówkach żądania. Muszą być przekazywane z klienta na każde żądanie uwierzytelnionego dostępu.",
"accessToken": "Token dostępu", "accessToken": "Token dostępu",
"usageExamples": "Przykłady użycia", "usageExamples": "Przykłady użycia",
"tokenId": "Token ID", "tokenId": "Identyfikator tokena",
"requestHeades": "Nagłówki żądania", "requestHeades": "Nagłówki żądania",
"queryParameter": "Parametr zapytania", "queryParameter": "Parametr zapytania",
"importantNote": "Ważna uwaga", "importantNote": "Ważna uwaga",
@ -177,8 +177,8 @@
"subdomnainDescription": "Poddomena, w której twój zasób będzie dostępny.", "subdomnainDescription": "Poddomena, w której twój zasób będzie dostępny.",
"resourceRawSettings": "Ustawienia TCP/UDP", "resourceRawSettings": "Ustawienia TCP/UDP",
"resourceRawSettingsDescription": "Skonfiguruj jak twój zasób będzie dostępny przez TCP/UDP", "resourceRawSettingsDescription": "Skonfiguruj jak twój zasób będzie dostępny przez TCP/UDP",
"protocol": "Protocol", "protocol": "Protokół",
"protocolSelect": "Select a protocol", "protocolSelect": "Wybierz protokół",
"resourcePortNumber": "Numer portu", "resourcePortNumber": "Numer portu",
"resourcePortNumberDescription": "Numer portu zewnętrznego do żądań proxy.", "resourcePortNumberDescription": "Numer portu zewnętrznego do żądań proxy.",
"cancel": "Anuluj", "cancel": "Anuluj",
@ -196,7 +196,7 @@
"disabled": "Wyłączone", "disabled": "Wyłączone",
"general": "Ogólny", "general": "Ogólny",
"generalSettings": "Ustawienia ogólne", "generalSettings": "Ustawienia ogólne",
"proxy": "Proxy", "proxy": "Serwer pośredniczący",
"rules": "Regulamin", "rules": "Regulamin",
"resourceSettingDescription": "Skonfiguruj ustawienia zasobu", "resourceSettingDescription": "Skonfiguruj ustawienia zasobu",
"resourceSetting": "Ustawienia {resourceName}", "resourceSetting": "Ustawienia {resourceName}",
@ -300,7 +300,7 @@
"userMessageConfirm": "Aby potwierdzić, wpisz nazwę użytkownika poniżej.", "userMessageConfirm": "Aby potwierdzić, wpisz nazwę użytkownika poniżej.",
"userQuestionRemove": "Czy na pewno chcesz trwale usunąć {selectedUser} z serwera?", "userQuestionRemove": "Czy na pewno chcesz trwale usunąć {selectedUser} z serwera?",
"licenseKey": "Klucz licencyjny", "licenseKey": "Klucz licencyjny",
"valid": "Valid", "valid": "Prawidłowy",
"numberOfSites": "Liczba witryn", "numberOfSites": "Liczba witryn",
"licenseKeySearch": "Szukaj kluczy licencyjnych...", "licenseKeySearch": "Szukaj kluczy licencyjnych...",
"licenseKeyAdd": "Dodaj klucz licencyjny", "licenseKeyAdd": "Dodaj klucz licencyjny",
@ -1100,7 +1100,7 @@
"containerImage": "Obraz", "containerImage": "Obraz",
"containerState": "Stan", "containerState": "Stan",
"containerNetworks": "Sieci", "containerNetworks": "Sieci",
"containerHostnameIp": "Hostname/IP", "containerHostnameIp": "Nazwa hosta/IP",
"containerLabels": "Etykiety", "containerLabels": "Etykiety",
"containerLabelsCount": "{count} etykieta{s,plural,one{} other{s}}", "containerLabelsCount": "{count} etykieta{s,plural,one{} other{s}}",
"containerLabelsTitle": "Etykiety kontenera", "containerLabelsTitle": "Etykiety kontenera",
@ -1127,6 +1127,10 @@
"noContainersFoundMatching": "Nie znaleziono kontenerów pasujących do \"{filter}\".", "noContainersFoundMatching": "Nie znaleziono kontenerów pasujących do \"{filter}\".",
"light": "jasny", "light": "jasny",
"dark": "ciemny", "dark": "ciemny",
"system": "system", "system": "System",
"theme": "Motyw" "theme": "Motyw",
} "initialSetupTitle": "Wstępna konfiguracja serwera",
"initialSetupDescription": "Utwórz początkowe konto administratora serwera. Może istnieć tylko jeden administrator serwera. Zawsze można zmienić te dane uwierzytelniające.",
"createAdminAccount": "Utwórz konto administratora",
"setupErrorCreateAdmin": "Wystąpił błąd podczas tworzenia konta administratora serwera."
}

View file

@ -114,7 +114,7 @@
"shareTokenDescription": "Seu token de acesso pode ser passado de duas maneiras: como um parâmetro de consulta ou nos cabeçalhos da solicitação. Estes devem ser passados do cliente em todas as solicitações para acesso autenticado.", "shareTokenDescription": "Seu token de acesso pode ser passado de duas maneiras: como um parâmetro de consulta ou nos cabeçalhos da solicitação. Estes devem ser passados do cliente em todas as solicitações para acesso autenticado.",
"accessToken": "Token de acesso", "accessToken": "Token de acesso",
"usageExamples": "Exemplos de uso", "usageExamples": "Exemplos de uso",
"tokenId": "Token ID", "tokenId": "ID do Token",
"requestHeades": "Cabeçalhos de solicitação", "requestHeades": "Cabeçalhos de solicitação",
"queryParameter": "Parâmetro de consulta", "queryParameter": "Parâmetro de consulta",
"importantNote": "Nota importante", "importantNote": "Nota importante",
@ -177,8 +177,8 @@
"subdomnainDescription": "O subdomínio onde seu recurso estará acessível.", "subdomnainDescription": "O subdomínio onde seu recurso estará acessível.",
"resourceRawSettings": "Configurações TCP/UDP", "resourceRawSettings": "Configurações TCP/UDP",
"resourceRawSettingsDescription": "Configure como seu recurso será acessado sobre TCP/UDP", "resourceRawSettingsDescription": "Configure como seu recurso será acessado sobre TCP/UDP",
"protocol": "Protocol", "protocol": "Protocolo",
"protocolSelect": "Select a protocol", "protocolSelect": "Selecione um protocolo",
"resourcePortNumber": "Número da Porta", "resourcePortNumber": "Número da Porta",
"resourcePortNumberDescription": "O número da porta externa para requisições de proxy.", "resourcePortNumberDescription": "O número da porta externa para requisições de proxy.",
"cancel": "cancelar", "cancel": "cancelar",
@ -300,7 +300,7 @@
"userMessageConfirm": "Para confirmar, por favor digite o nome do usuário abaixo.", "userMessageConfirm": "Para confirmar, por favor digite o nome do usuário abaixo.",
"userQuestionRemove": "Tem certeza que deseja excluir o {selectedUser} permanentemente do servidor?", "userQuestionRemove": "Tem certeza que deseja excluir o {selectedUser} permanentemente do servidor?",
"licenseKey": "Chave de Licença", "licenseKey": "Chave de Licença",
"valid": "Valid", "valid": "Válido",
"numberOfSites": "Número de sites", "numberOfSites": "Número de sites",
"licenseKeySearch": "Pesquisar chaves da licença...", "licenseKeySearch": "Pesquisar chaves da licença...",
"licenseKeyAdd": "Adicionar chave de licença", "licenseKeyAdd": "Adicionar chave de licença",
@ -1102,9 +1102,9 @@
"containerNetworks": "Redes", "containerNetworks": "Redes",
"containerHostnameIp": "Hostname/IP", "containerHostnameIp": "Hostname/IP",
"containerLabels": "Marcadores", "containerLabels": "Marcadores",
"containerLabelsCount": "{count} label{s,plural,one{} other{s}}", "containerLabelsCount": "{count} rótulo{s,plural,one{} other{s}}",
"containerLabelsTitle": "Etiquetas do Contêiner", "containerLabelsTitle": "Etiquetas do Contêiner",
"containerLabelEmpty": "<empty>", "containerLabelEmpty": "<vazio>",
"containerPorts": "Portas", "containerPorts": "Portas",
"containerPortsMore": "+ Mais{count}", "containerPortsMore": "+ Mais{count}",
"containerActions": "Ações.", "containerActions": "Ações.",
@ -1114,7 +1114,7 @@
"showStoppedContainers": "Mostrar contêineres parados", "showStoppedContainers": "Mostrar contêineres parados",
"noContainersFound": "Nenhum contêiner encontrado. Certifique-se de que os contêineres Docker estão em execução.", "noContainersFound": "Nenhum contêiner encontrado. Certifique-se de que os contêineres Docker estão em execução.",
"searchContainersPlaceholder": "Pesquisar entre os contêineres {count}...", "searchContainersPlaceholder": "Pesquisar entre os contêineres {count}...",
"searchResultsCount": "{count} result{s,plural,one{} other{s}}", "searchResultsCount": "{count} resultado{s,plural,one{} other{s}}",
"filters": "Filtros", "filters": "Filtros",
"filterOptions": "Opções de Filtro", "filterOptions": "Opções de Filtro",
"filterPorts": "Portas", "filterPorts": "Portas",
@ -1128,5 +1128,9 @@
"light": "claro", "light": "claro",
"dark": "escuro", "dark": "escuro",
"system": "sistema", "system": "sistema",
"theme": "Tema" "theme": "Tema",
} "initialSetupTitle": "Configuração Inicial do Servidor",
"initialSetupDescription": "Crie a conta de administrador inicial do servidor. Apenas um administrador do servidor pode existir. Você sempre pode alterar essas credenciais posteriormente.",
"createAdminAccount": "Criar Conta de Administrador",
"setupErrorCreateAdmin": "Ocorreu um erro ao criar a conta de administrador do servidor."
}

View file

@ -1128,5 +1128,9 @@
"light": "açık", "light": "açık",
"dark": "koyu", "dark": "koyu",
"system": "sistem", "system": "sistem",
"theme": "Tema" "theme": "Tema",
} "initialSetupTitle": "İlk Sunucu Kurulumu",
"initialSetupDescription": "İlk sunucu yönetici hesabını oluşturun. Yalnızca bir sunucu yöneticisi olabilir. Bu kimlik bilgilerini daha sonra her zaman değiştirebilirsiniz.",
"createAdminAccount": "Yönetici Hesabı Oluştur",
"setupErrorCreateAdmin": "Sunucu yönetici hesabı oluşturulurken bir hata oluştu."
}

View file

@ -12,7 +12,7 @@
"componentsErrorNoMember": "您目前不是任何组织的成员。", "componentsErrorNoMember": "您目前不是任何组织的成员。",
"welcome": "欢迎使用 Pangolin", "welcome": "欢迎使用 Pangolin",
"componentsCreateOrg": "创建组织", "componentsCreateOrg": "创建组织",
"componentsMember": "You're a member of {count, plural, =0 {no organization} =1 {one organization} other {# organizations}}.", "componentsMember": "您属于 {count, plural, =0 {无组织} =1 {一个组织} other {# 个组织}}。",
"componentsInvalidKey": "检测到无效或过期的许可证密钥。按照许可证条款操作以继续使用所有功能。", "componentsInvalidKey": "检测到无效或过期的许可证密钥。按照许可证条款操作以继续使用所有功能。",
"dismiss": "忽略", "dismiss": "忽略",
"componentsLicenseViolation": "许可证超限:该服务器使用了 {usedSites} 个站点,已超过授权的 {maxSites} 个。请遵守许可证条款以继续使用全部功能。", "componentsLicenseViolation": "许可证超限:该服务器使用了 {usedSites} 个站点,已超过授权的 {maxSites} 个。请遵守许可证条款以继续使用全部功能。",
@ -66,8 +66,8 @@
"siteLoadWGConfig": "正在载入 WireGuard 配置...", "siteLoadWGConfig": "正在载入 WireGuard 配置...",
"siteDocker": "扩展 Docker 部署详细信息", "siteDocker": "扩展 Docker 部署详细信息",
"toggle": "切换", "toggle": "切换",
"dockerCompose": "Docker Compose", "dockerCompose": "Docker 配置",
"dockerRun": "Docker Run", "dockerRun": "停靠栏",
"siteLearnLocal": "本地站点不需要隧道连接,点击了解更多", "siteLearnLocal": "本地站点不需要隧道连接,点击了解更多",
"siteConfirmCopy": "我已经复制了配置信息", "siteConfirmCopy": "我已经复制了配置信息",
"searchSitesProgress": "搜索站点...", "searchSitesProgress": "搜索站点...",
@ -331,7 +331,7 @@
"fossorialLicense": "查看Fossorial Commercial License和订阅条款", "fossorialLicense": "查看Fossorial Commercial License和订阅条款",
"licenseMessageRemove": "这将删除许可证密钥和它授予的所有相关权限。", "licenseMessageRemove": "这将删除许可证密钥和它授予的所有相关权限。",
"licenseMessageConfirm": "要确认,请在下面输入许可证密钥。", "licenseMessageConfirm": "要确认,请在下面输入许可证密钥。",
"licenseQuestionRemove": "Are you sure you want to delete the license key {selectedKey} ?", "licenseQuestionRemove": "您确定要删除 {selectedKey} 的邀请吗?",
"licenseKeyDelete": "删除许可证密钥", "licenseKeyDelete": "删除许可证密钥",
"licenseKeyDeleteConfirm": "确认删除许可证密钥", "licenseKeyDeleteConfirm": "确认删除许可证密钥",
"licenseTitle": "管理许可证状态", "licenseTitle": "管理许可证状态",
@ -465,7 +465,7 @@
"siteErrorFetchDescription": "获取资源时出错", "siteErrorFetchDescription": "获取资源时出错",
"targetErrorDuplicate": "重复的目标", "targetErrorDuplicate": "重复的目标",
"targetErrorDuplicateDescription": "具有这些设置的目标已存在", "targetErrorDuplicateDescription": "具有这些设置的目标已存在",
"targetWireGuardErrorInvalidIp": "Invalid target IP", "targetWireGuardErrorInvalidIp": "无效的目标IP",
"targetWireGuardErrorInvalidIpDescription": "目标IP必须在站点子网内", "targetWireGuardErrorInvalidIpDescription": "目标IP必须在站点子网内",
"targetsUpdated": "目标已更新", "targetsUpdated": "目标已更新",
"targetsUpdatedDescription": "目标和设置更新成功", "targetsUpdatedDescription": "目标和设置更新成功",
@ -691,7 +691,7 @@
"accessRoleErrorRemove": "删除角色失败", "accessRoleErrorRemove": "删除角色失败",
"accessRoleErrorRemoveDescription": "删除角色时出错。", "accessRoleErrorRemoveDescription": "删除角色时出错。",
"accessRoleName": "角色名称", "accessRoleName": "角色名称",
"accessRoleQuestionRemove": "You're about to delete the {name} role. You cannot undo this action.", "accessRoleQuestionRemove": "您即将删除 {name} 角色。 此操作无法撤销。",
"accessRoleRemove": "删除角色", "accessRoleRemove": "删除角色",
"accessRoleRemoveDescription": "从组织中删除角色", "accessRoleRemoveDescription": "从组织中删除角色",
"accessRoleRemoveSubmit": "删除角色", "accessRoleRemoveSubmit": "删除角色",
@ -822,7 +822,7 @@
"emailVerifyResend": "没有收到代码?点击此处重新发送", "emailVerifyResend": "没有收到代码?点击此处重新发送",
"passwordNotMatch": "密码不匹配", "passwordNotMatch": "密码不匹配",
"signupError": "注册时出错", "signupError": "注册时出错",
"pangolinLogoAlt": "Pangolin Logo", "pangolinLogoAlt": "Pangolin 标志",
"inviteAlready": "看起来您已被邀请!", "inviteAlready": "看起来您已被邀请!",
"inviteAlreadyDescription": "要接受邀请,您必须登录或创建一个帐户。", "inviteAlreadyDescription": "要接受邀请,您必须登录或创建一个帐户。",
"signupQuestion": "已经有一个帐户?", "signupQuestion": "已经有一个帐户?",
@ -881,7 +881,7 @@
"idpOidcTokenValidating": "正在验证 OIDC 令牌", "idpOidcTokenValidating": "正在验证 OIDC 令牌",
"idpOidcTokenResponse": "验证 OIDC 令牌响应", "idpOidcTokenResponse": "验证 OIDC 令牌响应",
"idpErrorOidcTokenValidating": "验证 OIDC 令牌出错", "idpErrorOidcTokenValidating": "验证 OIDC 令牌出错",
"idpConnectingTo": "Connecting to {name}", "idpConnectingTo": "连接到{name}",
"idpConnectingToDescription": "正在验证您的身份", "idpConnectingToDescription": "正在验证您的身份",
"idpConnectingToProcess": "正在连接...", "idpConnectingToProcess": "正在连接...",
"idpConnectingToFinished": "已连接", "idpConnectingToFinished": "已连接",
@ -895,7 +895,7 @@
"inviteErrorExpired": "邀请可能已过期", "inviteErrorExpired": "邀请可能已过期",
"inviteErrorRevoked": "邀请可能已被吊销了", "inviteErrorRevoked": "邀请可能已被吊销了",
"inviteErrorTypo": "邀请链接中可能有一个类型", "inviteErrorTypo": "邀请链接中可能有一个类型",
"pangolinSetup": "Setup - Pangolin", "pangolinSetup": "认证 - Pangolin",
"orgNameRequired": "组织名称是必需的", "orgNameRequired": "组织名称是必需的",
"orgIdRequired": "组织ID是必需的", "orgIdRequired": "组织ID是必需的",
"orgErrorCreate": "创建组织时出错", "orgErrorCreate": "创建组织时出错",
@ -1094,7 +1094,7 @@
"enableDockerSocketDescription": "启用 Docker Socket 发现以填充容器信息。必须向 Newt 提供 Socket 路径。", "enableDockerSocketDescription": "启用 Docker Socket 发现以填充容器信息。必须向 Newt 提供 Socket 路径。",
"enableDockerSocketLink": "了解更多", "enableDockerSocketLink": "了解更多",
"viewDockerContainers": "查看停靠容器", "viewDockerContainers": "查看停靠容器",
"containersIn": "Containers in {siteName}", "containersIn": "{siteName} 中的容器",
"selectContainerDescription": "选择任何容器作为目标的主机名。点击端口使用端口。", "selectContainerDescription": "选择任何容器作为目标的主机名。点击端口使用端口。",
"containerName": "名称", "containerName": "名称",
"containerImage": "图片", "containerImage": "图片",
@ -1128,5 +1128,9 @@
"light": "浅色", "light": "浅色",
"dark": "深色", "dark": "深色",
"system": "系统", "system": "系统",
"theme": "主题" "theme": "主题",
} "initialSetupTitle": "初始服务器设置",
"initialSetupDescription": "创建初始服务器管理员帐户。 只能存在一个服务器管理员。 您可以随时更改这些凭据。",
"createAdminAccount": "创建管理员帐户",
"setupErrorCreateAdmin": "创建服务器管理员帐户时出错。"
}

View file

@ -5,6 +5,12 @@ import { withReplicas } from "drizzle-orm/pg-core";
function createDb() { function createDb() {
const config = readConfigFile(); const config = readConfigFile();
if (!config.postgres) {
throw new Error(
"Postgres configuration is missing in the configuration file."
);
}
const connectionString = config.postgres?.connection_string; const connectionString = config.postgres?.connection_string;
const replicaConnections = config.postgres?.replicas || []; const replicaConnections = config.postgres?.replicas || [];

View file

@ -5,7 +5,6 @@ import path from "path";
import fs from "fs/promises"; import fs from "fs/promises";
import { APP_PATH } from "@server/lib/consts"; import { APP_PATH } from "@server/lib/consts";
import { existsSync, mkdirSync } from "fs"; import { existsSync, mkdirSync } from "fs";
import { readConfigFile } from "@server/lib/readConfigFile";
export const location = path.join(APP_PATH, "db", "db.sqlite"); export const location = path.join(APP_PATH, "db", "db.sqlite");
export const exists = await checkFileExists(location); export const exists = await checkFileExists(location);
@ -13,8 +12,6 @@ export const exists = await checkFileExists(location);
bootstrapVolume(); bootstrapVolume();
function createDb() { function createDb() {
const config = readConfigFile();
const sqlite = new Database(location); const sqlite = new Database(location);
return DrizzleSqlite(sqlite, { schema }); return DrizzleSqlite(sqlite, { schema });
} }

View file

@ -5,6 +5,7 @@ import { SupporterKey, supporterKey } from "@server/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { license } from "@server/license/license"; import { license } from "@server/license/license";
import { configSchema, readConfigFile } from "./readConfigFile"; import { configSchema, readConfigFile } from "./readConfigFile";
import { fromError } from "zod-validation-error";
export class Config { export class Config {
private rawConfig!: z.infer<typeof configSchema>; private rawConfig!: z.infer<typeof configSchema>;
@ -20,7 +21,35 @@ export class Config {
} }
public load() { public load() {
const parsedConfig = readConfigFile(); const environment = readConfigFile();
const {
data: parsedConfig,
success,
error
} = configSchema.safeParse(environment);
if (!success) {
const errors = fromError(error);
throw new Error(`Invalid configuration file: ${errors}`);
}
if (process.env.APP_BASE_DOMAIN) {
console.log(
"WARNING: You're using deprecated environment variables. Transition to the configuration file. https://docs.fossorial.io/"
);
}
if (
// @ts-ignore
parsedConfig.users ||
process.env.USERS_SERVERADMIN_EMAIL ||
process.env.USERS_SERVERADMIN_PASSWORD
) {
console.log(
"WARNING: Your admin credentials are still in the config file or environment variables. This method of setting admin credentials is no longer supported. It is recommended to remove them."
);
}
process.env.APP_VERSION = APP_VERSION; process.env.APP_VERSION = APP_VERSION;

View file

@ -2,7 +2,7 @@ import path from "path";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
// This is a placeholder value replaced by the build process // This is a placeholder value replaced by the build process
export const APP_VERSION = "1.5.1"; export const APP_VERSION = "1.6.0";
export const __FILENAME = fileURLToPath(import.meta.url); export const __FILENAME = fileURLToPath(import.meta.url);
export const __DIRNAME = path.dirname(__FILENAME); export const __DIRNAME = path.dirname(__FILENAME);

View file

@ -295,24 +295,11 @@ export function readConfigFile() {
environment = loadConfig(configFilePath2); environment = loadConfig(configFilePath2);
} }
if (process.env.APP_BASE_DOMAIN) {
console.log(
"You're using deprecated environment variables. Transition to the configuration file. https://docs.fossorial.io/"
);
}
if (!environment) { if (!environment) {
throw new Error( throw new Error(
"No configuration file found. Please create one. https://docs.fossorial.io/" "No configuration file found. Please create one. https://docs.fossorial.io/"
); );
} }
const parsedConfig = configSchema.safeParse(environment); return environment;
if (!parsedConfig.success) {
const errors = fromError(parsedConfig.error);
throw new Error(`Invalid configuration file: ${errors}`);
}
return parsedConfig.data;
} }

View file

@ -1,4 +1,4 @@
import { rateLimit } from "express-rate-limit"; import { MemoryStore, rateLimit, Store } from "express-rate-limit";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import logger from "@server/logger"; import logger from "@server/logger";
@ -6,7 +6,15 @@ import HttpCode from "@server/types/HttpCode";
import config from "@server/lib/config"; import config from "@server/lib/config";
import { RedisStore } from "rate-limit-redis"; import { RedisStore } from "rate-limit-redis";
import redisManager from "@server/db/redis"; import redisManager from "@server/db/redis";
import { Command as RedisCommand } from "ioredis";
export let rateLimitStore: Store = new MemoryStore();
if (config.getRawConfig().flags?.enable_redis) {
const client = redisManager.client!;
rateLimitStore = new RedisStore({
sendCommand: async (command: string, ...args: string[]) =>
(await client.call(command, args)) as any
});
}
export function rateLimitMiddleware({ export function rateLimitMiddleware({
windowMin, windowMin,
@ -19,11 +27,8 @@ export function rateLimitMiddleware({
type: "IP_ONLY" | "IP_AND_PATH"; type: "IP_ONLY" | "IP_AND_PATH";
skipCondition?: (req: Request, res: Response) => boolean; skipCondition?: (req: Request, res: Response) => boolean;
}) { }) {
const enableRedis = config.getRawConfig().flags?.enable_redis;
let opts;
if (type === "IP_AND_PATH") { if (type === "IP_AND_PATH") {
opts = { return rateLimit({
windowMs: windowMin * 60 * 1000, windowMs: windowMin * 60 * 1000,
max, max,
skip: skipCondition, skip: skipCondition,
@ -38,10 +43,11 @@ export function rateLimitMiddleware({
return next( return next(
createHttpError(HttpCode.TOO_MANY_REQUESTS, message) createHttpError(HttpCode.TOO_MANY_REQUESTS, message)
); );
} },
} as any; store: rateLimitStore
});
} else { } else {
opts = { return rateLimit({
windowMs: windowMin * 60 * 1000, windowMs: windowMin * 60 * 1000,
max, max,
skip: skipCondition, skip: skipCondition,
@ -52,18 +58,8 @@ export function rateLimitMiddleware({
createHttpError(HttpCode.TOO_MANY_REQUESTS, message) createHttpError(HttpCode.TOO_MANY_REQUESTS, message)
); );
} }
};
}
if (enableRedis) {
const client = redisManager.client!;
opts.store = new RedisStore({
sendCommand: async (command: string, ...args: string[]) =>
(await client.call(command, args)) as any
}); });
} }
return rateLimit(opts);
} }
export default rateLimitMiddleware; export default rateLimitMiddleware;

View file

@ -32,6 +32,7 @@ import {
verifyIsLoggedInUser, verifyIsLoggedInUser,
verifyClientAccess, verifyClientAccess,
verifyApiKeyAccess, verifyApiKeyAccess,
rateLimitStore,
} from "@server/middlewares"; } from "@server/middlewares";
import { verifyUserHasAction } from "../middlewares/verifyUserHasAction"; import { verifyUserHasAction } from "../middlewares/verifyUserHasAction";
import { ActionsEnum } from "@server/auth/actions"; import { ActionsEnum } from "@server/auth/actions";
@ -782,7 +783,8 @@ authRouter.post(
handler: (req, res, next) => { handler: (req, res, next) => {
const message = `You can only request an email verification code ${3} times every ${15} minutes. Please try again later.`; const message = `You can only request an email verification code ${3} times every ${15} minutes. Please try again later.`;
return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message)); return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message));
} },
store: rateLimitStore
}), }),
auth.requestEmailVerificationCode auth.requestEmailVerificationCode
); );
@ -802,7 +804,8 @@ authRouter.post(
handler: (req, res, next) => { handler: (req, res, next) => {
const message = `You can only request a password reset ${3} times every ${15} minutes. Please try again later.`; const message = `You can only request a password reset ${3} times every ${15} minutes. Please try again later.`;
return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message)); return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message));
} },
store: rateLimitStore
}), }),
auth.requestPasswordReset auth.requestPasswordReset
); );
@ -821,7 +824,8 @@ authRouter.post(
handler: (req, res, next) => { handler: (req, res, next) => {
const message = `You can only request an email OTP ${10} times every ${15} minutes. Please try again later.`; const message = `You can only request an email OTP ${10} times every ${15} minutes. Please try again later.`;
return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message)); return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message));
} },
store: rateLimitStore
}), }),
resource.authWithWhitelist resource.authWithWhitelist
); );

View file

@ -33,7 +33,6 @@ export default async function Page(props: {
>(`/auth/initial-setup-complete`, await authCookieHeader()); >(`/auth/initial-setup-complete`, await authCookieHeader());
const complete = setupRes.data.data.complete; const complete = setupRes.data.data.complete;
if (!complete) { if (!complete) {
console.log("compelte", complete);
redirect("/auth/initial-setup"); redirect("/auth/initial-setup");
} }

View file

@ -308,13 +308,13 @@ export default function StepperForm() {
)} )}
/> />
{orgIdTaken && ( {orgIdTaken && !orgCreated ? (
<Alert variant="destructive"> <Alert variant="destructive">
<AlertDescription> <AlertDescription>
{t('setupErrorIdentifier')} {t('setupErrorIdentifier')}
</AlertDescription> </AlertDescription>
</Alert> </Alert>
)} ) : null}
{error && ( {error && (
<Alert variant="destructive"> <Alert variant="destructive">