mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-04 01:55:10 +02:00
I18n orgId/settings (#21)
* New translation keys in en-US locale * New translation keys in de-DE locale * New translation keys in fr-FR locale * New translation keys in it-IT locale * New translation keys in pl-PL locale * New translation keys in pt-PT locale * New translation keys in tr-TR locale * Add translation keys if settings/resources/resourceId/authentication * New translation keys in en-US locale * New translation keys in de-DE locale * New translation keys in fr-FR locale * New translation keys in it-IT locale * New translation keys in pl-PL locale * New translation keys in pt-PT locale * New translation keys in tr-TR locale * Add translation keys if settings/resources/resourceId/general * Small naming fix * New translation keys in en-US locale * New translation keys in de-DE locale * New translation keys in fr-FR locale * New translation keys in it-IT locale * New translation keys in pl-PL locale * New translation keys in pt-PT locale * New translation keys in tr-TR locale * Add translation keys if settings/access/roles * New translation keys in en-US locale * New translation keys in de-DE locale * New translation keys in fr-FR locale * New translation keys in it-IT locale * New translation keys in pl-PL locale * New translation keys in pt-PT locale * New translation keys in tr-TR locale * Add translation keys in orgId/settings * Fixes after merge * Fixes after merge * Fixes after merge * Small fix * Fix build
This commit is contained in:
parent
6f54e3da9e
commit
96bfc3cf36
49 changed files with 2749 additions and 590 deletions
|
@ -71,7 +71,7 @@
|
|||
"dockerRun": "Docker Run",
|
||||
"siteLearnLocal": "Lokale Sites nicht Tunnel, erfahren Sie mehr",
|
||||
"siteConfirmCopy": "Ich habe die Konfiguration kopiert",
|
||||
"searchSites": "Seiten suchen...",
|
||||
"searchSitesProgress": "Seiten suchen...",
|
||||
"siteAdd": "Site hinzufügen",
|
||||
"siteInstallNewt": "Neustart installieren",
|
||||
"siteInstallNewtDescription": "Lass Newt auf deinem System laufen",
|
||||
|
@ -111,7 +111,7 @@
|
|||
"shareErrorDelete": "Link konnte nicht gelöscht werden",
|
||||
"shareErrorDeleteMessage": "Fehler beim Löschen des Links",
|
||||
"shareDeleted": "Link gelöscht",
|
||||
"shareDeletedDesciption": "Der Link wurde gelöscht",
|
||||
"shareDeletedDescription": "Der Link wurde gelöscht",
|
||||
"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",
|
||||
"usageExamples": "Nutzungsbeispiele",
|
||||
|
@ -234,7 +234,7 @@
|
|||
"username": "Benutzername",
|
||||
"identityProvider": "Identitätsanbieter",
|
||||
"role": "Rolle",
|
||||
"accessRoleNameRequired": "Name ist erforderlich",
|
||||
"nameRequired": "Name ist erforderlich",
|
||||
"accessRolesManage": "Rollen verwalten",
|
||||
"accessRolesDescription": "Konfigurieren Sie Rollen, um den Zugriff auf Ihre Organisation zu verwalten",
|
||||
"accessRolesSearch": "Rollen suchen...",
|
||||
|
@ -382,5 +382,319 @@
|
|||
"inviteValidityPeriodSelect": "Gültigkeitszeitraum auswählen",
|
||||
"inviteRegenerateMessage": "Die Einladung wurde neu generiert. Der Benutzer muss den untenstehenden Link aufrufen, um die Einladung anzunehmen.",
|
||||
"inviteRegenerateButton": "Neu generieren",
|
||||
"expiresAt": "Läuft ab am"
|
||||
"expiresAt": "Läuft ab am",
|
||||
"accessRoleUnknown": "Unbekannte Rolle",
|
||||
"placeholder": "Platzhalter",
|
||||
"userErrorOrgRemove": "Fehler beim Entfernen des Benutzers",
|
||||
"userErrorOrgRemoveDescription": "Beim Entfernen des Benutzers ist ein Fehler aufgetreten.",
|
||||
"userOrgRemoved": "Benutzer entfernt",
|
||||
"userOrgRemovedDescription": "Der Benutzer {email} wurde aus der Organisation entfernt.",
|
||||
"userQuestionOrgRemove": "Sind Sie sicher, dass Sie <b>{email}</b> aus der Organisation entfernen möchten?",
|
||||
"userMessageOrgRemove": "Nach dem Entfernen hat dieser Benutzer keinen Zugriff mehr auf die Organisation. Sie können ihn später jederzeit wieder einladen, aber er muss die Einladung erneut annehmen.",
|
||||
"userMessageOrgConfirm": "Geben Sie zur Bestätigung den Namen des Benutzers unten ein.",
|
||||
"userRemoveOrgConfirm": "Entfernen des Benutzers bestätigen",
|
||||
"userRemoveOrg": "Benutzer aus der Organisation entfernen",
|
||||
"users": "Benutzer",
|
||||
"accessRoleMember": "Mitglied",
|
||||
"accessRoleOwner": "Eigentümer",
|
||||
"userConfirmed": "Bestätigt",
|
||||
"idpNameInternal": "Intern",
|
||||
"emailInvalid": "Ungültige E-Mail-Adresse",
|
||||
"inviteValidityDuration": "Bitte wählen Sie eine Dauer",
|
||||
"accessRoleSelectPlease": "Bitte wählen Sie eine Rolle",
|
||||
"usernameRequired": "Benutzername ist erforderlich",
|
||||
"idpSelectPlease": "Bitte wählen Sie einen Identitätsanbieter",
|
||||
"idpGenericOidc": "Generischer OAuth2/OIDC-Anbieter.",
|
||||
"accessRoleErrorFetch": "Fehler beim Abrufen der Rollen",
|
||||
"accessRoleErrorFetchDescription": "Beim Abrufen der Rollen ist ein Fehler aufgetreten",
|
||||
"idpErrorFetch": "Fehler beim Abrufen der Identitätsanbieter",
|
||||
"idpErrorFetchDescription": "Beim Abrufen der Identitätsanbieter ist ein Fehler aufgetreten",
|
||||
"userErrorExists": "Benutzer existiert bereits",
|
||||
"userErrorExistsDescription": "Dieser Benutzer ist bereits Mitglied der Organisation.",
|
||||
"inviteError": "Fehler beim Einladen des Benutzers",
|
||||
"inviteErrorDescription": "Beim Einladen des Benutzers ist ein Fehler aufgetreten",
|
||||
"userInvited": "Benutzer eingeladen",
|
||||
"userInvitedDescription": "Der Benutzer wurde erfolgreich eingeladen.",
|
||||
"userErrorCreate": "Fehler beim Erstellen des Benutzers",
|
||||
"userErrorCreateDescription": "Beim Erstellen des Benutzers ist ein Fehler aufgetreten",
|
||||
"userCreated": "Benutzer erstellt",
|
||||
"userCreatedDescription": "Der Benutzer wurde erfolgreich erstellt.",
|
||||
"userTypeInternal": "Interner Benutzer",
|
||||
"userTypeInternalDescription": "Laden Sie einen Benutzer direkt in Ihre Organisation ein.",
|
||||
"userTypeExternal": "Externer Benutzer",
|
||||
"userTypeExternalDescription": "Erstellen Sie einen Benutzer mit einem externen Identitätsanbieter.",
|
||||
"accessUserCreateDescription": "Folgen Sie den Schritten unten, um einen neuen Benutzer zu erstellen",
|
||||
"userSeeAll": "Alle Benutzer anzeigen",
|
||||
"userTypeTitle": "Benutzertyp",
|
||||
"userTypeDescription": "Legen Sie fest, wie Sie den Benutzer erstellen möchten",
|
||||
"userSettings": "Benutzerinformationen",
|
||||
"userSettingsDescription": "Geben Sie die Details für den neuen Benutzer ein",
|
||||
"inviteEmailSent": "Einladungs-E-Mail an Benutzer senden",
|
||||
"inviteValid": "Gültig für",
|
||||
"selectDuration": "Dauer auswählen",
|
||||
"accessRoleSelect": "Rolle auswählen",
|
||||
"inviteEmailSentDescription": "Eine E-Mail mit dem Zugangslink wurde an den Benutzer gesendet. Er muss den Link aufrufen, um die Einladung anzunehmen.",
|
||||
"inviteSentDescription": "Der Benutzer wurde eingeladen. Er muss den unten stehenden Link aufrufen, um die Einladung anzunehmen.",
|
||||
"inviteExpiresIn": "Die Einladung läuft in <b>{days, plural, =1 {einem Tag} other {# Tagen}}</b> ab.",
|
||||
"idpTitle": "Identitätsanbieter",
|
||||
"idpSelect": "Wählen Sie den Identitätsanbieter für den externen Benutzer",
|
||||
"idpNotConfigured": "Es sind keine Identitätsanbieter konfiguriert. Bitte konfigurieren Sie einen Identitätsanbieter, bevor Sie externe Benutzer erstellen.",
|
||||
"usernameUniq": "Dies muss mit dem eindeutigen Benutzernamen übereinstimmen, der im ausgewählten Identitätsanbieter existiert.",
|
||||
"emailOptional": "E-Mail (Optional)",
|
||||
"nameOptional": "Name (Optional)",
|
||||
"accessControls": "Zugriffskontrolle",
|
||||
"userDescription2": "Verwalten Sie die Einstellungen dieses Benutzers",
|
||||
"accessRoleErrorAdd": "Fehler beim Hinzufügen des Benutzers zur Rolle",
|
||||
"accessRoleErrorAddDescription": "Beim Hinzufügen des Benutzers zur Rolle ist ein Fehler aufgetreten.",
|
||||
"userSaved": "Benutzer gespeichert",
|
||||
"userSavedDescription": "Der Benutzer wurde aktualisiert.",
|
||||
"accessControlsDescription": "Verwalten Sie, worauf dieser Benutzer in der Organisation zugreifen und was er tun kann",
|
||||
"accessControlsSubmit": "Zugriffskontrollen speichern",
|
||||
"roles": "Rollen",
|
||||
"accessUsersRoles": "Benutzer & Rollen verwalten",
|
||||
"accessUsersRolesDescription": "Laden Sie Benutzer ein und fügen Sie sie zu Rollen hinzu, um den Zugriff auf Ihre Organisation zu verwalten",
|
||||
"key": "Schlüssel",
|
||||
"createdAt": "Erstellt am",
|
||||
"proxyErrorInvalidHeader": "Ungültiger benutzerdefinierter Host-Header-Wert. Verwenden Sie das Domänennamensformat oder speichern Sie leer, um den benutzerdefinierten Host-Header zu deaktivieren.",
|
||||
"proxyErrorTls": "Ungültiger TLS-Servername. Verwenden Sie das Domänennamensformat oder speichern Sie leer, um den TLS-Servernamen zu entfernen.",
|
||||
"targetErrorFetch": "Fehler beim Abrufen der Ziele",
|
||||
"targetErrorFetchDescription": "Beim Abrufen der Ziele ist ein Fehler aufgetreten",
|
||||
"siteErrorFetch": "Fehler beim Abrufen der Ressource",
|
||||
"siteErrorFetchDescription": "Beim Abrufen der Ressource ist ein Fehler aufgetreten",
|
||||
"targetErrorDuplicate": "Doppeltes Ziel",
|
||||
"targetErrorDuplicateDescription": "Ein Ziel mit diesen Einstellungen existiert bereits",
|
||||
"targetWireGuardErrorInvalidIp": "Ungültige Ziel-IP",
|
||||
"targetWireGuardErrorInvalidIpDescription": "Die Ziel-IP muss innerhalb des Site-Subnets liegen",
|
||||
"targetsUpdated": "Ziele aktualisiert",
|
||||
"targetsUpdatedDescription": "Ziele und Einstellungen erfolgreich aktualisiert",
|
||||
"targetsErrorUpdate": "Fehler beim Aktualisieren der Ziele",
|
||||
"targetsErrorUpdateDescription": "Beim Aktualisieren der Ziele ist ein Fehler aufgetreten",
|
||||
"targetTlsUpdate": "TLS-Einstellungen aktualisiert",
|
||||
"targetTlsUpdateDescription": "Ihre TLS-Einstellungen wurden erfolgreich aktualisiert",
|
||||
"targetErrorTlsUpdate": "Fehler beim Aktualisieren der TLS-Einstellungen",
|
||||
"targetErrorTlsUpdateDescription": "Beim Aktualisieren der TLS-Einstellungen ist ein Fehler aufgetreten",
|
||||
"proxyUpdated": "Proxy-Einstellungen aktualisiert",
|
||||
"proxyUpdatedDescription": "Ihre Proxy-Einstellungen wurden erfolgreich aktualisiert",
|
||||
"proxyErrorUpdate": "Fehler beim Aktualisieren der Proxy-Einstellungen",
|
||||
"proxyErrorUpdateDescription": "Beim Aktualisieren der Proxy-Einstellungen ist ein Fehler aufgetreten",
|
||||
"targetAddr": "IP / Hostname",
|
||||
"targetPort": "Port",
|
||||
"targetProtocol": "Protokoll",
|
||||
"targetTlsSettings": "HTTPS & TLS Einstellungen",
|
||||
"targetTlsSettingsDescription": "Konfigurieren Sie TLS-Einstellungen für Ihre Ressource",
|
||||
"targetTlsSettingsAdvanced": "Erweiterte TLS-Einstellungen",
|
||||
"targetTlsSni": "TLS-Servername (SNI)",
|
||||
"targetTlsSniDescription": "Der zu verwendende TLS-Servername für SNI. Leer lassen, um den Standard zu verwenden.",
|
||||
"targetTlsSubmit": "Einstellungen speichern",
|
||||
"targets": "Ziel-Konfiguration",
|
||||
"targetsDescription": "Richten Sie Ziele ein, um Datenverkehr zu Ihren Diensten zu leiten",
|
||||
"targetStickySessions": "Sticky Sessions aktivieren",
|
||||
"targetStickySessionsDescription": "Verbindungen für die gesamte Sitzung auf demselben Backend-Ziel halten.",
|
||||
"methodSelect": "Methode auswählen",
|
||||
"targetSubmit": "Ziel hinzufügen",
|
||||
"targetNoOne": "Keine Ziele. Fügen Sie ein Ziel über das Formular hinzu.",
|
||||
"targetNoOneDescription": "Das Hinzufügen von mehr als einem Ziel aktiviert den Lastausgleich.",
|
||||
"targetsSubmit": "Ziele speichern",
|
||||
"proxyAdditional": "Zusätzliche Proxy-Einstellungen",
|
||||
"proxyAdditionalDescription": "Konfigurieren Sie, wie Ihre Ressource mit Proxy-Einstellungen umgeht",
|
||||
"proxyCustomHeader": "Benutzerdefinierter Host-Header",
|
||||
"proxyCustomHeaderDescription": "Der Host-Header, der beim Weiterleiten von Anfragen gesetzt werden soll. Leer lassen, um den Standard zu verwenden.",
|
||||
"proxyAdditionalSubmit": "Proxy-Einstellungen speichern",
|
||||
"subnetMaskErrorInvalid": "Ungültige Subnetzmaske. Muss zwischen 0 und 32 liegen.",
|
||||
"ipAddressErrorInvalidFormat": "Ungültiges IP-Adressformat",
|
||||
"ipAddressErrorInvalidOctet": "Ungültiges IP-Adress-Oktett",
|
||||
"path": "Pfad",
|
||||
"ipAddressRange": "IP-Bereich",
|
||||
"rulesErrorFetch": "Fehler beim Abrufen der Regeln",
|
||||
"rulesErrorFetchDescription": "Beim Abrufen der Regeln ist ein Fehler aufgetreten",
|
||||
"rulesErrorDuplicate": "Doppelte Regel",
|
||||
"rulesErrorDuplicateDescription": "Eine Regel mit diesen Einstellungen existiert bereits",
|
||||
"rulesErrorInvalidIpAddressRange": "Ungültiger CIDR",
|
||||
"rulesErrorInvalidIpAddressRangeDescription": "Bitte geben Sie einen gültigen CIDR-Wert ein",
|
||||
"rulesErrorInvalidUrl": "Ungültiger URL-Pfad",
|
||||
"rulesErrorInvalidUrlDescription": "Bitte geben Sie einen gültigen URL-Pfad-Wert ein",
|
||||
"rulesErrorInvalidIpAddress": "Ungültige IP",
|
||||
"rulesErrorInvalidIpAddressDescription": "Bitte geben Sie eine gültige IP-Adresse ein",
|
||||
"rulesErrorUpdate": "Fehler beim Aktualisieren der Regeln",
|
||||
"rulesErrorUpdateDescription": "Beim Aktualisieren der Regeln ist ein Fehler aufgetreten",
|
||||
"rulesUpdated": "Regeln aktivieren",
|
||||
"rulesUpdatedDescription": "Die Regelauswertung wurde aktualisiert",
|
||||
"rulesMatchIpAddressRangeDescription": "Geben Sie eine Adresse im CIDR-Format ein (z.B. 103.21.244.0/22)",
|
||||
"rulesMatchIpAddress": "Geben Sie eine IP-Adresse ein (z.B. 103.21.244.12)",
|
||||
"rulesMatchUrl": "Geben Sie einen URL-Pfad oder -Muster ein (z.B. /api/v1/todos oder /api/v1/*)",
|
||||
"rulesErrorInvalidPriority": "Ungültige Priorität",
|
||||
"rulesErrorInvalidPriorityDescription": "Bitte geben Sie eine gültige Priorität ein",
|
||||
"rulesErrorDuplicatePriority": "Doppelte Prioritäten",
|
||||
"rulesErrorDuplicatePriorityDescription": "Bitte geben Sie eindeutige Prioritäten ein",
|
||||
"ruleUpdated": "Regeln aktualisiert",
|
||||
"ruleUpdatedDescription": "Regeln erfolgreich aktualisiert",
|
||||
"ruleErrorUpdate": "Operation fehlgeschlagen",
|
||||
"ruleErrorUpdateDescription": "Während des Speichervorgangs ist ein Fehler aufgetreten",
|
||||
"rulesPriority": "Priorität",
|
||||
"rulesAction": "Aktion",
|
||||
"rulesMatchType": "Übereinstimmungstyp",
|
||||
"value": "Wert",
|
||||
"rulesAbout": "Über Regeln",
|
||||
"rulesAboutDescription": "Mit Regeln können Sie den Zugriff auf Ihre Ressource anhand verschiedener Kriterien steuern. Sie können Regeln erstellen, um den Zugriff basierend auf IP-Adresse oder URL-Pfad zu erlauben oder zu verweigern.",
|
||||
"rulesActions": "Aktionen",
|
||||
"rulesActionAlwaysAllow": "Immer erlauben: Alle Authentifizierungsmethoden umgehen",
|
||||
"rulesActionAlwaysDeny": "Immer verweigern: Alle Anfragen blockieren; keine Authentifizierung möglich",
|
||||
"rulesMatchCriteria": "Übereinstimmungskriterien",
|
||||
"rulesMatchCriteriaIpAddress": "Mit einer bestimmten IP-Adresse übereinstimmen",
|
||||
"rulesMatchCriteriaIpAddressRange": "Mit einem IP-Adressbereich in CIDR-Notation übereinstimmen",
|
||||
"rulesMatchCriteriaUrl": "Mit einem URL-Pfad oder -Muster übereinstimmen",
|
||||
"rulesEnable": "Regeln aktivieren",
|
||||
"rulesEnableDescription": "Regelauswertung für diese Ressource aktivieren oder deaktivieren",
|
||||
"rulesResource": "Ressourcen-Regelkonfiguration",
|
||||
"rulesResourceDescription": "Konfigurieren Sie Regeln zur Steuerung des Zugriffs auf Ihre Ressource",
|
||||
"ruleSubmit": "Regel hinzufügen",
|
||||
"rulesNoOne": "Keine Regeln. Fügen Sie eine Regel über das Formular hinzu.",
|
||||
"rulesOrder": "Regeln werden nach aufsteigender Priorität ausgewertet.",
|
||||
"rulesSubmit": "Regeln speichern",
|
||||
"resourceErrorCreate": "Fehler beim Erstellen der Ressource",
|
||||
"resourceErrorCreateDescription": "Beim Erstellen der Ressource ist ein Fehler aufgetreten",
|
||||
"resourceErrorCreateMessage": "Fehler beim Erstellen der Ressource:",
|
||||
"resourceErrorCreateMessageDescription": "Ein unerwarteter Fehler ist aufgetreten",
|
||||
"sitesErrorFetch": "Fehler beim Abrufen der Sites",
|
||||
"sitesErrorFetchDescription": "Beim Abrufen der Sites ist ein Fehler aufgetreten",
|
||||
"domainsErrorFetch": "Fehler beim Abrufen der Domains",
|
||||
"domainsErrorFetchDescription": "Beim Abrufen der Domains ist ein Fehler aufgetreten",
|
||||
"none": "Keine",
|
||||
"unknown": "Unbekannt",
|
||||
"resources": "Ressourcen",
|
||||
"resourcesDescription": "Ressourcen sind Proxies zu Anwendungen in Ihrem privaten Netzwerk. Erstellen Sie eine Ressource für jeden HTTP/HTTPS- oder rohen TCP/UDP-Dienst in Ihrem privaten Netzwerk. Jede Ressource muss mit einer Site verbunden sein, um private, sichere Konnektivität über einen verschlüsselten WireGuard-Tunnel zu ermöglichen.",
|
||||
"resourcesWireGuardConnect": "Sichere Verbindung mit WireGuard-Verschlüsselung",
|
||||
"resourcesMultipleAuthenticationMethods": "Mehrere Authentifizierungsmethoden konfigurieren",
|
||||
"resourcesUsersRolesAccess": "Benutzer- und rollenbasierte Zugriffskontrolle",
|
||||
"resourcesErrorUpdate": "Fehler beim Umschalten der Ressource",
|
||||
"resourcesErrorUpdateDescription": "Beim Aktualisieren der Ressource ist ein Fehler aufgetreten",
|
||||
"access": "Zugriff",
|
||||
"shareLink": "{resource} Freigabe-Link",
|
||||
"resourceSelect": "Ressource auswählen",
|
||||
"shareLinks": "Freigabe-Links",
|
||||
"share": "Teilbare Links",
|
||||
"shareDescription2": "Erstellen Sie teilbare Links zu Ihren Ressourcen. Links bieten temporären oder unbegrenzten Zugriff auf Ihre Ressource. Sie können die Ablaufzeit des Links bei der Erstellung konfigurieren.",
|
||||
"shareEasyCreate": "Einfach zu erstellen und zu teilen",
|
||||
"shareConfigurableExpirationDuration": "Konfigurierbare Ablaufzeit",
|
||||
"shareSecureAndRevocable": "Sicher und widerrufbar",
|
||||
"nameMin": "Name muss mindestens {len} Zeichen lang sein.",
|
||||
"nameMax": "Name darf nicht länger als {len} Zeichen sein.",
|
||||
"sitesConfirmCopy": "Bitte bestätigen Sie, dass Sie die Konfiguration kopiert haben.",
|
||||
"unknownCommand": "Unbekannter Befehl",
|
||||
"newtErrorFetchReleases": "Fehler beim Abrufen der Release-Informationen: {err}",
|
||||
"newtErrorFetchLatest": "Fehler beim Abrufen der neuesten Version: {err}",
|
||||
"newtEndpoint": "Newt-Endpunkt",
|
||||
"newtId": "Newt-ID",
|
||||
"newtSecretKey": "Newt-Geheimschlüssel",
|
||||
"architecture": "Architektur",
|
||||
"sites": "Sites",
|
||||
"siteWgAnyClients": "Verwenden Sie einen beliebigen WireGuard-Client zur Verbindung. Sie müssen Ihre internen Ressourcen über die Peer-IP adressieren.",
|
||||
"siteWgCompatibleAllClients": "Kompatibel mit allen WireGuard-Clients",
|
||||
"siteWgManualConfigurationRequired": "Manuelle Konfiguration erforderlich",
|
||||
"userErrorNotAdminOrOwner": "Benutzer ist kein Administrator oder Eigentümer",
|
||||
"pangolinSettings": "Einstellungen - Pangolin",
|
||||
"accessRoleYour": "Ihre Rolle:",
|
||||
"accessRoleSelect2": "Wähle eine Rolle",
|
||||
"accessUserSelect": "Wähle einen Benutzer",
|
||||
"otpEmailEnter": "E-Mail-Adresse eingeben",
|
||||
"otpEmailEnterDescription": "Drücken Sie Enter, um eine E-Mail nach der Eingabe im Eingabefeld hinzuzufügen.",
|
||||
"otpEmailErrorInvalid": "Ungültige E-Mail-Adresse. Platzhalter (*) muss der gesamte lokale Teil sein.",
|
||||
"otpEmailSmtpRequired": "SMTP erforderlich",
|
||||
"otpEmailSmtpRequiredDescription": "SMTP muss auf dem Server aktiviert sein, um die Einmal-Passwort-Authentifizierung zu verwenden.",
|
||||
"otpEmailTitle": "Einmal-Passwörter",
|
||||
"otpEmailTitleDescription": "E-Mail-basierte Authentifizierung für Ressourcenzugriff erforderlich",
|
||||
"otpEmailWhitelist": "E-Mail-Whitelist",
|
||||
"otpEmailWhitelistList": "Zugelassene E-Mails",
|
||||
"otpEmailWhitelistListDescription": "Nur Benutzer mit diesen E-Mail-Adressen können auf diese Ressource zugreifen. Sie werden aufgefordert, ein an ihre E-Mail gesendetes Einmal-Passwort einzugeben. Platzhalter (*@example.com) können verwendet werden, um E-Mail-Adressen einer Domain zuzulassen.",
|
||||
"otpEmailWhitelistSave": "Whitelist speichern",
|
||||
"passwordAdd": "Passwort hinzufügen",
|
||||
"passwordRemove": "Passwort entfernen",
|
||||
"pincodeAdd": "PIN-Code hinzufügen",
|
||||
"pincodeRemove": "PIN-Code entfernen",
|
||||
"resourceAuthMethods": "Authentifizierungsmethoden",
|
||||
"resourceAuthMethodsDescriptions": "Ermöglichen Sie den Zugriff auf die Ressource über zusätzliche Authentifizierungsmethoden",
|
||||
"resourceAuthSettingsSave": "Erfolgreich gespeichert",
|
||||
"resourceAuthSettingsSaveDescription": "Authentifizierungseinstellungen wurden gespeichert",
|
||||
"resourceErrorAuthFetch": "Fehler beim Abrufen der Daten",
|
||||
"resourceErrorAuthFetchDescription": "Beim Abrufen der Daten ist ein Fehler aufgetreten",
|
||||
"resourceErrorPasswordRemove": "Fehler beim Entfernen des Ressourcenpassworts",
|
||||
"resourceErrorPasswordRemoveDescription": "Beim Entfernen des Ressourcenpassworts ist ein Fehler aufgetreten",
|
||||
"resourceErrorPasswordSetup": "Fehler beim Einrichten des Ressourcenpassworts",
|
||||
"resourceErrorPasswordSetupDescription": "Beim Einrichten des Ressourcenpassworts ist ein Fehler aufgetreten",
|
||||
"resourceErrorPincodeRemove": "Fehler beim Entfernen des Ressourcen-PIN-Codes",
|
||||
"resourceErrorPincodeRemoveDescription": "Beim Entfernen des Ressourcen-PIN-Codes ist ein Fehler aufgetreten",
|
||||
"resourceErrorPincodeSetup": "Fehler beim Einrichten des Ressourcen-PIN-Codes",
|
||||
"resourceErrorPincodeSetupDescription": "Beim Einrichten des Ressourcen-PIN-Codes ist ein Fehler aufgetreten",
|
||||
"resourceErrorUsersRolesSave": "Fehler beim Speichern der Rollen",
|
||||
"resourceErrorUsersRolesSaveDescription": "Beim Speichern der Rollen ist ein Fehler aufgetreten",
|
||||
"resourceErrorWhitelistSave": "Fehler beim Speichern der Whitelist",
|
||||
"resourceErrorWhitelistSaveDescription": "Beim Speichern der Whitelist ist ein Fehler aufgetreten",
|
||||
"resourcePasswordSubmit": "Passwortschutz aktivieren",
|
||||
"resourcePasswordRemove": "Ressourcenpasswort entfernt",
|
||||
"resourcePasswordRemoveDescription": "Das Ressourcenpasswort wurde erfolgreich entfernt",
|
||||
"resourcePasswordSetup": "Ressourcenpasswort festgelegt",
|
||||
"resourcePasswordSetupDescription": "Das Ressourcenpasswort wurde erfolgreich festgelegt",
|
||||
"resourcePasswordSetupTitle": "Passwort festlegen",
|
||||
"resourcePasswordSetupTitleDescription": "Legen Sie ein Passwort fest, um diese Ressource zu schützen",
|
||||
"resourcePincode": "PIN-Code",
|
||||
"resourcePincodeSubmit": "PIN-Code-Schutz aktivieren",
|
||||
"resourcePincodeProtection": "PIN-Code-Schutz {status}",
|
||||
"resourcePincodeRemove": "Ressourcen-PIN-Code entfernt",
|
||||
"resourcePincodeRemoveDescription": "Der Ressourcen-PIN-Code wurde erfolgreich entfernt",
|
||||
"resourcePincodeSetup": "Ressourcen-PIN-Code festgelegt",
|
||||
"resourcePincodeSetupDescription": "Der Ressourcen-PIN-Code wurde erfolgreich festgelegt",
|
||||
"resourcePincodeSetupTitle": "PIN-Code festlegen",
|
||||
"resourcePincodeSetupTitleDescription": "Legen Sie einen PIN-Code fest, um diese Ressource zu schützen",
|
||||
"resourceRoleDescription": "Administratoren haben immer Zugriff auf diese Ressource.",
|
||||
"resourceUsersRoles": "Benutzer & Rollen",
|
||||
"resourceUsersRolesDescription": "Konfigurieren Sie, welche Benutzer und Rollen diese Ressource besuchen können",
|
||||
"resourceUsersRolesSubmit": "Benutzer & Rollen speichern",
|
||||
"resourceWhitelistSave": "Erfolgreich gespeichert",
|
||||
"resourceWhitelistSaveDescription": "Whitelist-Einstellungen wurden gespeichert",
|
||||
"ssoUse": "Plattform SSO verwenden",
|
||||
"ssoUseDescription": "Bestehende Benutzer müssen sich nur einmal für alle Ressourcen anmelden, bei denen dies aktiviert ist.",
|
||||
"proxyErrorInvalidPort": "Ungültige Portnummer",
|
||||
"subdomainErrorInvalid": "Ungültige Subdomain",
|
||||
"domainErrorFetch": "Fehler beim Abrufen der Domains",
|
||||
"domainErrorFetchDescription": "Beim Abrufen der Domains ist ein Fehler aufgetreten",
|
||||
"resourceErrorUpdate": "Ressource konnte nicht aktualisiert werden",
|
||||
"resourceErrorUpdateDescription": "Beim Aktualisieren der Ressource ist ein Fehler aufgetreten",
|
||||
"resourceUpdated": "Ressource aktualisiert",
|
||||
"resourceUpdatedDescription": "Die Ressource wurde erfolgreich aktualisiert",
|
||||
"resourceErrorTransfer": "Ressource konnte nicht übertragen werden",
|
||||
"resourceErrorTransferDescription": "Beim Übertragen der Ressource ist ein Fehler aufgetreten",
|
||||
"resourceTransferred": "Ressource übertragen",
|
||||
"resourceTransferredDescription": "Die Ressource wurde erfolgreich übertragen",
|
||||
"resourceErrorToggle": "Ressource konnte nicht umgeschaltet werden",
|
||||
"resourceErrorToggleDescription": "Beim Aktualisieren der Ressource ist ein Fehler aufgetreten",
|
||||
"resourceVisibilityTitle": "Sichtbarkeit",
|
||||
"resourceVisibilityTitleDescription": "Ressourcensichtbarkeit vollständig aktivieren oder deaktivieren",
|
||||
"resourceGeneral": "Allgemeine Einstellungen",
|
||||
"resourceGeneralDescription": "Konfigurieren Sie die allgemeinen Einstellungen für diese Ressource",
|
||||
"resourceEnable": "Ressource aktivieren",
|
||||
"resourceTransfer": "Ressource übertragen",
|
||||
"resourceTransferDescription": "Diese Ressource auf eine andere Site übertragen",
|
||||
"resourceTransferSubmit": "Ressource übertragen",
|
||||
"siteDestination": "Zielsite",
|
||||
"searchSites": "Sites durchsuchen",
|
||||
"accessRoleCreate": "Rolle erstellen",
|
||||
"accessRoleCreateDescription": "Erstellen Sie eine neue Rolle, um Benutzer zu gruppieren und ihre Berechtigungen zu verwalten.",
|
||||
"accessRoleCreateSubmit": "Rolle erstellen",
|
||||
"accessRoleCreated": "Rolle erstellt",
|
||||
"accessRoleCreatedDescription": "Die Rolle wurde erfolgreich erstellt.",
|
||||
"accessRoleErrorCreate": "Fehler beim Erstellen der Rolle",
|
||||
"accessRoleErrorCreateDescription": "Beim Erstellen der Rolle ist ein Fehler aufgetreten.",
|
||||
"accessRoleErrorNewRequired": "Neue Rolle ist erforderlich",
|
||||
"accessRoleErrorRemove": "Fehler beim Entfernen der Rolle",
|
||||
"accessRoleErrorRemoveDescription": "Beim Entfernen der Rolle ist ein Fehler aufgetreten.",
|
||||
"accessRoleName": "Rollenname",
|
||||
"accessRoleQuestionRemove": "Sie sind dabei, die Rolle <b>{name}</b> zu löschen. Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"accessRoleRemove": "Rolle entfernen",
|
||||
"accessRoleRemoveDescription": "Eine Rolle aus der Organisation entfernen",
|
||||
"accessRoleRemoveSubmit": "Rolle entfernen",
|
||||
"accessRoleRemoved": "Rolle entfernt",
|
||||
"accessRoleRemovedDescription": "Die Rolle wurde erfolgreich entfernt.",
|
||||
"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",
|
||||
"sitesNotFound": "Keine Sites gefunden."
|
||||
}
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
"siteCreateDescription2": "Follow the steps below to create and connect a new site",
|
||||
"siteCreateDescription": "Create a new site to start connecting your resources",
|
||||
"close": "Close",
|
||||
"siteNameMin": "Name must be at least 2 characters.",
|
||||
"siteNameMax": "Name must not be longer than 30 characters.",
|
||||
"siteErrorCreate": "Error creating site",
|
||||
"siteErrorCreateKeyPair": "Key pair or site defaults not found",
|
||||
"siteErrorCreateDefaults": "Site defaults not found",
|
||||
|
@ -71,7 +69,7 @@
|
|||
"dockerRun": "Docker Run",
|
||||
"siteLearnLocal": "Local sites do not tunnel, learn more",
|
||||
"siteConfirmCopy": "I have copied the config",
|
||||
"searchSites": "Search sites...",
|
||||
"searchSitesProgress": "Search sites...",
|
||||
"siteAdd": "Add Site",
|
||||
"siteInstallNewt": "Install Newt",
|
||||
"siteInstallNewtDescription": "Get Newt running on your system",
|
||||
|
@ -111,7 +109,7 @@
|
|||
"shareErrorDelete": "Failed to delete link",
|
||||
"shareErrorDeleteMessage": "An error occurred deleting link",
|
||||
"shareDeleted": "Link deleted",
|
||||
"shareDeletedDesciption": "The link has been deleted",
|
||||
"shareDeletedDescription": "The link has been deleted",
|
||||
"shareTokenDescription": "Your access token can be passed in two ways: as a query parameter or in the request headers. These must be passed from the client on every request for authenticated access.",
|
||||
"accessToken": "Access Token",
|
||||
"usageExamples": "Usage Examples",
|
||||
|
@ -234,7 +232,7 @@
|
|||
"username": "Username",
|
||||
"identityProvider": "Identity Provider",
|
||||
"role": "Role",
|
||||
"accessRoleNameRequired": "Name is required",
|
||||
"nameRequired": "Name is required",
|
||||
"accessRolesManage": "Manage Roles",
|
||||
"accessRolesDescription": "Configure roles to manage access to your organization",
|
||||
"accessRolesSearch": "Search roles...",
|
||||
|
@ -252,8 +250,6 @@
|
|||
"years": "Years",
|
||||
"day": "{count, plural, =1 {# day} other {# days}}",
|
||||
"apiKeysTitle": "API Key Information",
|
||||
"apiKeysNameMin": "Name must be at least 2 characters.",
|
||||
"apiKeysNameMax": "Name must not be longer than 255 characters.",
|
||||
"apiKeysConfirmCopy2": "You must confirm that you have copied the API key.",
|
||||
"apiKeysErrorCreate": "Error creating API key",
|
||||
"apiKeysErrorSetPermission": "Error setting permissions",
|
||||
|
@ -382,5 +378,319 @@
|
|||
"inviteValidityPeriodSelect": "Select validity period",
|
||||
"inviteRegenerateMessage": "The invitation has been regenerated. The user must access the link below to accept the invitation.",
|
||||
"inviteRegenerateButton": "Regenerate",
|
||||
"expiresAt": "Expires At"
|
||||
"expiresAt": "Expires At",
|
||||
"accessRoleUnknown": "Unknown Role",
|
||||
"placeholder": "Placeholder",
|
||||
"userErrorOrgRemove": "Failed to remove user",
|
||||
"userErrorOrgRemoveDescription": "An error occurred while removing the user.",
|
||||
"userOrgRemoved": "User removed",
|
||||
"userOrgRemovedDescription": "The user {email} has been removed from the organization.",
|
||||
"userQuestionOrgRemove": "Are you sure you want to remove <b>{email}</b> from the organization?",
|
||||
"userMessageOrgRemove": "Once removed, this user will no longer have access to the organization. You can always re-invite them later, but they will need to accept the invitation again.",
|
||||
"userMessageOrgConfirm": "To confirm, please type the name of the of the user below.",
|
||||
"userRemoveOrgConfirm": "Confirm Remove User",
|
||||
"userRemoveOrg": "Remove User from Organization",
|
||||
"users": "Users",
|
||||
"accessRoleMember": "Member",
|
||||
"accessRoleOwner": "Owner",
|
||||
"userConfirmed": "Confirmed",
|
||||
"idpNameInternal": "Internal",
|
||||
"emailInvalid": "Invalid email address",
|
||||
"inviteValidityDuration": "Please select a duration",
|
||||
"accessRoleSelectPlease": "Please select a role",
|
||||
"usernameRequired": "Username is required",
|
||||
"idpSelectPlease": "Please select an identity provider",
|
||||
"idpGenericOidc": "Generic OAuth2/OIDC provider.",
|
||||
"accessRoleErrorFetch": "Failed to fetch roles",
|
||||
"accessRoleErrorFetchDescription": "An error occurred while fetching the roles",
|
||||
"idpErrorFetch": "Failed to fetch identity providers",
|
||||
"idpErrorFetchDescription": "An error occurred while fetching identity providers",
|
||||
"userErrorExists": "User Already Exists",
|
||||
"userErrorExistsDescription": "This user is already a member of the organization.",
|
||||
"inviteError": "Failed to invite user",
|
||||
"inviteErrorDescription": "An error occurred while inviting the user",
|
||||
"userInvited": "User invited",
|
||||
"userInvitedDescription": "The user has been successfully invited.",
|
||||
"userErrorCreate": "Failed to create user",
|
||||
"userErrorCreateDescription": "An error occurred while creating the user",
|
||||
"userCreated": "User created",
|
||||
"userCreatedDescription": "The user has been successfully created.",
|
||||
"userTypeInternal": "Internal User",
|
||||
"userTypeInternalDescription": "Invite a user to join your organization directly.",
|
||||
"userTypeExternal": "External User",
|
||||
"userTypeExternalDescription": "Create a user with an external identity provider.",
|
||||
"accessUserCreateDescription": "Follow the steps below to create a new user",
|
||||
"userSeeAll": "See All Users",
|
||||
"userTypeTitle": "User Type",
|
||||
"userTypeDescription": "Determine how you want to create the user",
|
||||
"userSettings": "User Information",
|
||||
"userSettingsDescription": "Enter the details for the new user",
|
||||
"inviteEmailSent": "Send invite email to user",
|
||||
"inviteValid": "Valid For",
|
||||
"selectDuration": "Select duration",
|
||||
"accessRoleSelect": "Select role",
|
||||
"inviteEmailSentDescription": "An email has been sent to the user with the access link below. They must access the link to accept the invitation.",
|
||||
"inviteSentDescription": "The user has been invited. They must access the link below to accept the invitation.",
|
||||
"inviteExpiresIn": "The invite will expire in <b>{days, plural, =1 {# day} other {# days}}</b>.",
|
||||
"idpTitle": "Identity Provider",
|
||||
"idpSelect": "Select the identity provider for the external user",
|
||||
"idpNotConfigured": "No identity providers are configured. Please configure an identity provider before creating external users.",
|
||||
"usernameUniq": "This must match the unique username that exists in the selected identity provider.",
|
||||
"emailOptional": "Email (Optional)",
|
||||
"nameOptional": "Name (Optional)",
|
||||
"accessControls": "Access Controls",
|
||||
"userDescription2": "Manage the settings on this user",
|
||||
"accessRoleErrorAdd": "Failed to add user to role",
|
||||
"accessRoleErrorAddDescription": "An error occurred while adding user to the role.",
|
||||
"userSaved": "User saved",
|
||||
"userSavedDescription": "The user has been updated.",
|
||||
"accessControlsDescription": "Manage what this user can access and do in the organization",
|
||||
"accessControlsSubmit": "Save Access Controls",
|
||||
"roles": "Roles",
|
||||
"accessUsersRoles": "Manage Users & Roles",
|
||||
"accessUsersRolesDescription": "Invite users and add them to roles to manage access to your organization",
|
||||
"key": "Key",
|
||||
"createdAt": "Created At",
|
||||
"proxyErrorInvalidHeader": "Invalid custom Host Header value. Use domain name format, or save empty to unset custom Host Header.",
|
||||
"proxyErrorTls": "Invalid TLS Server Name. Use domain name format, or save empty to remove the TLS Server Name.",
|
||||
"targetErrorFetch": "Failed to fetch targets",
|
||||
"targetErrorFetchDescription": "An error occurred while fetching targets",
|
||||
"siteErrorFetch": "Failed to fetch resource",
|
||||
"siteErrorFetchDescription": "An error occurred while fetching resource",
|
||||
"targetErrorDuplicate": "Duplicate target",
|
||||
"targetErrorDuplicateDescription": "A target with these settings already exists",
|
||||
"targetWireGuardErrorInvalidIp": "Invalid target IP",
|
||||
"targetWireGuardErrorInvalidIpDescription": "Target IP must be within the site subnet",
|
||||
"targetsUpdated": "Targets updated",
|
||||
"targetsUpdatedDescription": "Targets and settings updated successfully",
|
||||
"targetsErrorUpdate": "Failed to update targets",
|
||||
"targetsErrorUpdateDescription": "An error occurred while updating targets",
|
||||
"targetTlsUpdate": "TLS settings updated",
|
||||
"targetTlsUpdateDescription": "Your TLS settings have been updated successfully",
|
||||
"targetErrorTlsUpdate": "Failed to update TLS settings",
|
||||
"targetErrorTlsUpdateDescription": "An error occurred while updating TLS settings",
|
||||
"proxyUpdated": "Proxy settings updated",
|
||||
"proxyUpdatedDescription": "Your proxy settings have been updated successfully",
|
||||
"proxyErrorUpdate": "Failed to update proxy settings",
|
||||
"proxyErrorUpdateDescription": "An error occurred while updating proxy settings",
|
||||
"targetAddr": "IP / Hostname",
|
||||
"targetPort": "Port",
|
||||
"targetProtocol": "Protocol",
|
||||
"targetTlsSettings": "HTTPS & TLS Settings",
|
||||
"targetTlsSettingsDescription": "Configure TLS settings for your resource",
|
||||
"targetTlsSettingsAdvanced": "Advanced TLS Settings",
|
||||
"targetTlsSni": "TLS Server Name (SNI)",
|
||||
"targetTlsSniDescription": "The TLS Server Name to use for SNI. Leave empty to use the default.",
|
||||
"targetTlsSubmit": "Save Settings",
|
||||
"targets": "Targets Configuration",
|
||||
"targetsDescription": "Set up targets to route traffic to your services",
|
||||
"targetStickySessions": "Enable Sticky Sessions",
|
||||
"targetStickySessionsDescription": "Keep connections on the same backend target for their entire session.",
|
||||
"methodSelect": "Select method",
|
||||
"targetSubmit": "Add Target",
|
||||
"targetNoOne": "No targets. Add a target using the form.",
|
||||
"targetNoOneDescription": "Adding more than one target above will enable load balancing.",
|
||||
"targetsSubmit": "Save Targets",
|
||||
"proxyAdditional": "Additional Proxy Settings",
|
||||
"proxyAdditionalDescription": "Configure how your resource handles proxy settings",
|
||||
"proxyCustomHeader": "Custom Host Header",
|
||||
"proxyCustomHeaderDescription": "The host header to set when proxying requests. Leave empty to use the default.",
|
||||
"proxyAdditionalSubmit": "Save Proxy Settings",
|
||||
"subnetMaskErrorInvalid": "Invalid subnet mask. Must be between 0 and 32.",
|
||||
"ipAddressErrorInvalidFormat": "Invalid IP address format",
|
||||
"ipAddressErrorInvalidOctet": "Invalid IP address octet",
|
||||
"path": "Path",
|
||||
"ipAddressRange": "IP Range",
|
||||
"rulesErrorFetch": "Failed to fetch rules",
|
||||
"rulesErrorFetchDescription": "An error occurred while fetching rules",
|
||||
"rulesErrorDuplicate": "Duplicate rule",
|
||||
"rulesErrorDuplicateDescription": "A rule with these settings already exists",
|
||||
"rulesErrorInvalidIpAddressRange": "Invalid CIDR",
|
||||
"rulesErrorInvalidIpAddressRangeDescription": "Please enter a valid CIDR value",
|
||||
"rulesErrorInvalidUrl": "Invalid URL path",
|
||||
"rulesErrorInvalidUrlDescription": "Please enter a valid URL path value",
|
||||
"rulesErrorInvalidIpAddress": "Invalid IP",
|
||||
"rulesErrorInvalidIpAddressDescription": "Please enter a valid IP address",
|
||||
"rulesErrorUpdate": "Failed to update rules",
|
||||
"rulesErrorUpdateDescription": "An error occurred while updating rules",
|
||||
"rulesUpdated": "Enable Rules",
|
||||
"rulesUpdatedDescription": "Rule evaluation has been updated",
|
||||
"rulesMatchIpAddressRangeDescription": "Enter an address in CIDR format (e.g., 103.21.244.0/22)",
|
||||
"rulesMatchIpAddress": "Enter an IP address (e.g., 103.21.244.12)",
|
||||
"rulesMatchUrl": "Enter a URL path or pattern (e.g., /api/v1/todos or /api/v1/*)",
|
||||
"rulesErrorInvalidPriority": "Invalid Priority",
|
||||
"rulesErrorInvalidPriorityDescription": "Please enter a valid priority",
|
||||
"rulesErrorDuplicatePriority": "Duplicate Priorities",
|
||||
"rulesErrorDuplicatePriorityDescription": "Please enter unique priorities",
|
||||
"ruleUpdated": "Rules updated",
|
||||
"ruleUpdatedDescription": "Rules updated successfully",
|
||||
"ruleErrorUpdate": "Operation failed",
|
||||
"ruleErrorUpdateDescription": "An error occurred during the save operation",
|
||||
"rulesPriority": "Priority",
|
||||
"rulesAction": "Action",
|
||||
"rulesMatchType": "Match Type",
|
||||
"value": "Value",
|
||||
"rulesAbout": "About Rules",
|
||||
"rulesAboutDescription": "Rules allow you to control access to your resource based on a set of criteria. You can create rules to allow or deny access based on IP address or URL path.",
|
||||
"rulesActions": "Actions",
|
||||
"rulesActionAlwaysAllow": "Always Allow: Bypass all authentication methods",
|
||||
"rulesActionAlwaysDeny": "Always Deny: Block all requests; no authentication can be attempted",
|
||||
"rulesMatchCriteria": "Matching Criteria",
|
||||
"rulesMatchCriteriaIpAddress": "Match a specific IP address",
|
||||
"rulesMatchCriteriaIpAddressRange": "Match a range of IP addresses in CIDR notation",
|
||||
"rulesMatchCriteriaUrl": "Match a URL path or pattern",
|
||||
"rulesEnable": "Enable Rules",
|
||||
"rulesEnableDescription": "Enable or disable rule evaluation for this resource",
|
||||
"rulesResource": "Resource Rules Configuration",
|
||||
"rulesResourceDescription": "Configure rules to control access to your resource",
|
||||
"ruleSubmit": "Add Rule",
|
||||
"rulesNoOne": "No rules. Add a rule using the form.",
|
||||
"rulesOrder": "Rules are evaluated by priority in ascending order.",
|
||||
"rulesSubmit": "Save Rules",
|
||||
"resourceErrorCreate": "Error creating resource",
|
||||
"resourceErrorCreateDescription": "An error occurred when creating the resource",
|
||||
"resourceErrorCreateMessage": "Error creating resource:",
|
||||
"resourceErrorCreateMessageDescription": "An unexpected error occurred",
|
||||
"sitesErrorFetch": "Error fetching sites",
|
||||
"sitesErrorFetchDescription": "An error occurred when fetching the sites",
|
||||
"domainsErrorFetch": "Error fetching domains",
|
||||
"domainsErrorFetchDescription": "An error occurred when fetching the domains",
|
||||
"none": "None",
|
||||
"unknown": "Unknown",
|
||||
"resources": "Resources",
|
||||
"resourcesDescription": "Resources are proxies to applications running on your private network. Create a resource for any HTTP/HTTPS or raw TCP/UDP service on your private network. Each resource must be connected to a site to enable private, secure connectivity through an encrypted WireGuard tunnel.",
|
||||
"resourcesWireGuardConnect": "Secure connectivity with WireGuard encryption",
|
||||
"resourcesMultipleAuthenticationMethods": "Configure multiple authentication methods",
|
||||
"resourcesUsersRolesAccess": "User and role-based access control",
|
||||
"resourcesErrorUpdate": "Failed to toggle resource",
|
||||
"resourcesErrorUpdateDescription": "An error occurred while updating the resource",
|
||||
"access": "Access",
|
||||
"shareLink": "{resource} Share Link",
|
||||
"resourceSelect": "Select resource",
|
||||
"shareLinks": "Share Links",
|
||||
"share": "Shareable Links",
|
||||
"shareDescription2": "Create shareable links to your resources. Links provide temporary or unlimited access to your resource. You can configure the expiration duration of the link when you create one.",
|
||||
"shareEasyCreate": "Easy to create and share",
|
||||
"shareConfigurableExpirationDuration": "Configurable expiration duration",
|
||||
"shareSecureAndRevocable": "Secure and revocable",
|
||||
"nameMin": "Name must be at least {len} characters.",
|
||||
"nameMax": "Name must not be longer than {len} characters.",
|
||||
"sitesConfirmCopy": "Please confirm that you have copied the config.",
|
||||
"unknownCommand": "Unknown command",
|
||||
"newtErrorFetchReleases": "Failed to fetch release info: {err}",
|
||||
"newtErrorFetchLatest": "Error fetching latest release: {err}",
|
||||
"newtEndpoint": "Newt Endpoint",
|
||||
"newtId": "Newt ID",
|
||||
"newtSecretKey": "Newt Secret Key",
|
||||
"architecture": "Architecture",
|
||||
"sites": "Sites",
|
||||
"siteWgAnyClients": "Use any WireGuard client to connect. You will have to address your internal resources using the peer IP.",
|
||||
"siteWgCompatibleAllClients": "Compatible with all WireGuard clients",
|
||||
"siteWgManualConfigurationRequired": "Manual configuration required",
|
||||
"userErrorNotAdminOrOwner": "User is not an admin or owner",
|
||||
"pangolinSettings": "Settings - Pangolin",
|
||||
"accessRoleYour": "Your role:",
|
||||
"accessRoleSelect2": "Select a role",
|
||||
"accessUserSelect": "Select a user",
|
||||
"otpEmailEnter": "Enter an email",
|
||||
"otpEmailEnterDescription": "Press enter to add an email after typing it in the input field.",
|
||||
"otpEmailErrorInvalid": "Invalid email address. Wildcard (*) must be the entire local part.",
|
||||
"otpEmailSmtpRequired": "SMTP Required",
|
||||
"otpEmailSmtpRequiredDescription": "SMTP must be enabled on the server to use one-time password authentication.",
|
||||
"otpEmailTitle": "One-time Passwords",
|
||||
"otpEmailTitleDescription": "Require email-based authentication for resource access",
|
||||
"otpEmailWhitelist": "Email Whitelist",
|
||||
"otpEmailWhitelistList": "Whitelisted Emails",
|
||||
"otpEmailWhitelistListDescription": "Only users with these email addresses will be able to access this resource. They will be prompted to enter a one-time password sent to their email. Wildcards (*@example.com) can be used to allow any email address from a domain.",
|
||||
"otpEmailWhitelistSave": "Save Whitelist",
|
||||
"passwordAdd": "Add Password",
|
||||
"passwordRemove": "Remove Password",
|
||||
"pincodeAdd": "Add PIN Code",
|
||||
"pincodeRemove": "Remove PIN Code",
|
||||
"resourceAuthMethods": "Authentication Methods",
|
||||
"resourceAuthMethodsDescriptions": "Allow access to the resource via additional auth methods",
|
||||
"resourceAuthSettingsSave": "Saved successfully",
|
||||
"resourceAuthSettingsSaveDescription": "Authentication settings have been saved",
|
||||
"resourceErrorAuthFetch": "Failed to fetch data",
|
||||
"resourceErrorAuthFetchDescription": "An error occurred while fetching the data",
|
||||
"resourceErrorPasswordRemove": "Error removing resource password",
|
||||
"resourceErrorPasswordRemoveDescription": "An error occurred while removing the resource password",
|
||||
"resourceErrorPasswordSetup": "Error setting resource password",
|
||||
"resourceErrorPasswordSetupDescription": "An error occurred while setting the resource password",
|
||||
"resourceErrorPincodeRemove": "Error removing resource pincode",
|
||||
"resourceErrorPincodeRemoveDescription": "An error occurred while removing the resource pincode",
|
||||
"resourceErrorPincodeSetup": "Error setting resource PIN code",
|
||||
"resourceErrorPincodeSetupDescription": "An error occurred while setting the resource PIN code",
|
||||
"resourceErrorUsersRolesSave": "Failed to set roles",
|
||||
"resourceErrorUsersRolesSaveDescription": "An error occurred while setting the roles",
|
||||
"resourceErrorWhitelistSave": "Failed to save whitelist",
|
||||
"resourceErrorWhitelistSaveDescription": "An error occurred while saving the whitelist",
|
||||
"resourcePasswordSubmit": "Enable Password Protection",
|
||||
"resourcePasswordRemove": "Resource password removed",
|
||||
"resourcePasswordRemoveDescription": "The resource password has been removed successfully",
|
||||
"resourcePasswordSetup": "Resource password set",
|
||||
"resourcePasswordSetupDescription": "The resource password has been set successfully",
|
||||
"resourcePasswordSetupTitle": "Set Password",
|
||||
"resourcePasswordSetupTitleDescription": "Set a password to protect this resource",
|
||||
"resourcePincode": "PIN Code",
|
||||
"resourcePincodeSubmit": "Enable PIN Code Protection",
|
||||
"resourcePincodeProtection": "PIN Code Protection {status}",
|
||||
"resourcePincodeRemove": "Resource pincode removed",
|
||||
"resourcePincodeRemoveDescription": "The resource password has been removed successfully",
|
||||
"resourcePincodeSetup": "Resource PIN code set",
|
||||
"resourcePincodeSetupDescription": "The resource pincode has been set successfully",
|
||||
"resourcePincodeSetupTitle": "Set Pincode",
|
||||
"resourcePincodeSetupTitleDescription": "Set a pincode to protect this resource",
|
||||
"resourceRoleDescription": "Admins can always access this resource.",
|
||||
"resourceUsersRoles": "Users & Roles",
|
||||
"resourceUsersRolesDescription": "Configure which users and roles can visit this resource",
|
||||
"resourceUsersRolesSubmit": "Save Users & Roles",
|
||||
"resourceWhitelistSave": "Saved successfully",
|
||||
"resourceWhitelistSaveDescription": "Whitelist settings have been saved",
|
||||
"ssoUse": "Use Platform SSO",
|
||||
"ssoUseDescription": "Existing users will only have to log in once for all resources that have this enabled.",
|
||||
"proxyErrorInvalidPort": "Invalid port number",
|
||||
"subdomainErrorInvalid": "Invalid subdomain",
|
||||
"domainErrorFetch": "Error fetching domains",
|
||||
"domainErrorFetchDescription": "An error occurred when fetching the domains",
|
||||
"resourceErrorUpdate": "Failed to update resource",
|
||||
"resourceErrorUpdateDescription": "An error occurred while updating the resource",
|
||||
"resourceUpdated": "Resource updated",
|
||||
"resourceUpdatedDescription": "The resource has been updated successfully",
|
||||
"resourceErrorTransfer": "Failed to transfer resource",
|
||||
"resourceErrorTransferDescription": "An error occurred while transferring the resource",
|
||||
"resourceTransferred": "Resource transferred",
|
||||
"resourceTransferredDescription": "The resource has been transferred successfully",
|
||||
"resourceErrorToggle": "Failed to toggle resource",
|
||||
"resourceErrorToggleDescription": "An error occurred while updating the resource",
|
||||
"resourceVisibilityTitle": "Visibility",
|
||||
"resourceVisibilityTitleDescription": "Completely enable or disable resource visibility",
|
||||
"resourceGeneral": "General Settings",
|
||||
"resourceGeneralDescription": "Configure the general settings for this resource",
|
||||
"resourceEnable": "Enable Resource",
|
||||
"resourceTransfer": "Transfer Resource",
|
||||
"resourceTransferDescription": "Transfer this resource to a different site",
|
||||
"resourceTransferSubmit": "Transfer Resource",
|
||||
"siteDestination": "Destination Site",
|
||||
"searchSites": "Search sites",
|
||||
"accessRoleCreate": "Create Role",
|
||||
"accessRoleCreateDescription": "Create a new role to group users and manage their permissions.",
|
||||
"accessRoleCreateSubmit": "Create Role",
|
||||
"accessRoleCreated": "Role created",
|
||||
"accessRoleCreatedDescription": "The role has been successfully created.",
|
||||
"accessRoleErrorCreate": "Failed to create role",
|
||||
"accessRoleErrorCreateDescription": "An error occurred while creating the role.",
|
||||
"accessRoleErrorNewRequired": "New role is required",
|
||||
"accessRoleErrorRemove": "Failed to remove role",
|
||||
"accessRoleErrorRemoveDescription": "An error occurred while removing the role.",
|
||||
"accessRoleName": "Role Name",
|
||||
"accessRoleQuestionRemove": "You're about to delete the <b>{name}</b> role. You cannot undo this action.",
|
||||
"accessRoleRemove": "Remove Role",
|
||||
"accessRoleRemoveDescription": "Remove a role from the organization",
|
||||
"accessRoleRemoveSubmit": "Remove Role",
|
||||
"accessRoleRemoved": "Role removed",
|
||||
"accessRoleRemovedDescription": "The role has been successfully removed.",
|
||||
"accessRoleRequiredRemove": "Before deleting this role, please select a new role to transfer existing members to.",
|
||||
"manage": "Manage",
|
||||
"sitesNotFound": "No sites found."
|
||||
}
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
"siteCreateDescription2": "Suivez les étapes ci-dessous pour créer et connecter un nouveau site",
|
||||
"siteCreateDescription": "Créez un nouveau site pour commencer à connecter vos ressources",
|
||||
"close": "Fermer",
|
||||
"siteNameMin": "Le nom doit comporter au moins 2 caractères.",
|
||||
"siteNameMax": "Le nom ne doit pas contenir plus de 30 caractères.",
|
||||
"siteErrorCreate": "Erreur lors de la création du site",
|
||||
"siteErrorCreateKeyPair": "Paire de clés ou site par défaut introuvable",
|
||||
"siteErrorCreateDefaults": "Les valeurs par défaut du site sont introuvables",
|
||||
|
@ -71,7 +69,7 @@
|
|||
"dockerRun": "Exécution Docker",
|
||||
"siteLearnLocal": "Les sites locaux ne tunnel, en savoir plus",
|
||||
"siteConfirmCopy": "J'ai copié la configuration",
|
||||
"searchSites": "Rechercher des sites...",
|
||||
"searchSitesProgress": "Rechercher des sites...",
|
||||
"siteAdd": "Ajouter un site",
|
||||
"siteInstallNewt": "Installer Newt",
|
||||
"siteInstallNewtDescription": "Faites fonctionner Newt sur votre système",
|
||||
|
@ -111,7 +109,7 @@
|
|||
"shareErrorDelete": "Impossible de supprimer le lien",
|
||||
"shareErrorDeleteMessage": "Une erreur s'est produite lors de la suppression du lien",
|
||||
"shareDeleted": "Lien supprimé",
|
||||
"shareDeletedDesciption": "Le lien a été supprimé",
|
||||
"shareDeletedDescription": "Le lien a été supprimé",
|
||||
"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",
|
||||
"usageExamples": "Exemples d'utilisation",
|
||||
|
@ -234,7 +232,7 @@
|
|||
"username": "Nom d'utilisateur",
|
||||
"identityProvider": "Fournisseur d'identité",
|
||||
"role": "Rôle",
|
||||
"accessRoleNameRequired": "Le nom est requis",
|
||||
"nameRequired": "Le nom est requis",
|
||||
"accessRolesManage": "Gérer les rôles",
|
||||
"accessRolesDescription": "Configurer les rôles pour gérer l'accès à votre organisation",
|
||||
"accessRolesSearch": "Rechercher des rôles...",
|
||||
|
@ -252,8 +250,6 @@
|
|||
"years": "Années",
|
||||
"day": "{count, plural, =1 {# jour} other {# jours}}",
|
||||
"apiKeysTitle": "Informations sur la clé API",
|
||||
"apiKeysNameMin": "Le nom doit comporter au moins 2 caractères.",
|
||||
"apiKeysNameMax": "Le nom ne doit pas dépasser 255 caractères.",
|
||||
"apiKeysConfirmCopy2": "Vous devez confirmer que vous avez copié la clé API.",
|
||||
"apiKeysErrorCreate": "Erreur lors de la création de la clé API",
|
||||
"apiKeysErrorSetPermission": "Erreur lors de la définition des permissions",
|
||||
|
@ -382,5 +378,319 @@
|
|||
"inviteValidityPeriodSelect": "Sélectionner la période de validité",
|
||||
"inviteRegenerateMessage": "L'invitation a été régénérée. L'utilisateur doit accéder au lien ci-dessous pour accepter l'invitation.",
|
||||
"inviteRegenerateButton": "Régénérer",
|
||||
"expiresAt": "Expire le"
|
||||
"expiresAt": "Expire le",
|
||||
"accessRoleUnknown": "Rôle inconnu",
|
||||
"placeholder": "Espace réservé",
|
||||
"userErrorOrgRemove": "Échec de la suppression de l'utilisateur",
|
||||
"userErrorOrgRemoveDescription": "Une erreur s'est produite lors de la suppression de l'utilisateur.",
|
||||
"userOrgRemoved": "Utilisateur supprimé",
|
||||
"userOrgRemovedDescription": "L'utilisateur {email} a été retiré de l'organisation.",
|
||||
"userQuestionOrgRemove": "Êtes-vous sûr de vouloir retirer <b>{email}</b> de l'organisation ?",
|
||||
"userMessageOrgRemove": "Une fois retiré, cet utilisateur n'aura plus accès à l'organisation. Vous pouvez toujours le réinviter plus tard, mais il devra accepter l'invitation à nouveau.",
|
||||
"userMessageOrgConfirm": "Pour confirmer, veuillez saisir le nom de l'utilisateur ci-dessous.",
|
||||
"userRemoveOrgConfirm": "Confirmer la suppression de l'utilisateur",
|
||||
"userRemoveOrg": "Retirer l'utilisateur de l'organisation",
|
||||
"users": "Utilisateurs",
|
||||
"accessRoleMember": "Membre",
|
||||
"accessRoleOwner": "Propriétaire",
|
||||
"userConfirmed": "Confirmé",
|
||||
"idpNameInternal": "Interne",
|
||||
"emailInvalid": "Adresse e-mail invalide",
|
||||
"inviteValidityDuration": "Veuillez sélectionner une durée",
|
||||
"accessRoleSelectPlease": "Veuillez sélectionner un rôle",
|
||||
"usernameRequired": "Le nom d'utilisateur est requis",
|
||||
"idpSelectPlease": "Veuillez sélectionner un fournisseur d'identité",
|
||||
"idpGenericOidc": "Fournisseur OAuth2/OIDC générique.",
|
||||
"accessRoleErrorFetch": "Échec de la récupération des rôles",
|
||||
"accessRoleErrorFetchDescription": "Une erreur s'est produite lors de la récupération des rôles",
|
||||
"idpErrorFetch": "Échec de la récupération des fournisseurs d'identité",
|
||||
"idpErrorFetchDescription": "Une erreur s'est produite lors de la récupération des fournisseurs d'identité",
|
||||
"userErrorExists": "L'utilisateur existe déjà",
|
||||
"userErrorExistsDescription": "Cet utilisateur est déjà membre de l'organisation.",
|
||||
"inviteError": "Échec de l'invitation de l'utilisateur",
|
||||
"inviteErrorDescription": "Une erreur s'est produite lors de l'invitation de l'utilisateur",
|
||||
"userInvited": "Utilisateur invité",
|
||||
"userInvitedDescription": "L'utilisateur a été invité avec succès.",
|
||||
"userErrorCreate": "Échec de la création de l'utilisateur",
|
||||
"userErrorCreateDescription": "Une erreur s'est produite lors de la création de l'utilisateur",
|
||||
"userCreated": "Utilisateur créé",
|
||||
"userCreatedDescription": "L'utilisateur a été créé avec succès.",
|
||||
"userTypeInternal": "Utilisateur interne",
|
||||
"userTypeInternalDescription": "Inviter un utilisateur à rejoindre votre organisation directement.",
|
||||
"userTypeExternal": "Utilisateur externe",
|
||||
"userTypeExternalDescription": "Créer un utilisateur avec un fournisseur d'identité externe.",
|
||||
"accessUserCreateDescription": "Suivez les étapes ci-dessous pour créer un nouvel utilisateur",
|
||||
"userSeeAll": "Voir tous les utilisateurs",
|
||||
"userTypeTitle": "Type d'utilisateur",
|
||||
"userTypeDescription": "Déterminez comment vous voulez créer l'utilisateur",
|
||||
"userSettings": "Informations utilisateur",
|
||||
"userSettingsDescription": "Entrez les détails du nouvel utilisateur",
|
||||
"inviteEmailSent": "Envoyer un e-mail d'invitation à l'utilisateur",
|
||||
"inviteValid": "Valide pour",
|
||||
"selectDuration": "Sélectionner la durée",
|
||||
"accessRoleSelect": "Sélectionner un rôle",
|
||||
"inviteEmailSentDescription": "Un e-mail a été envoyé à l'utilisateur avec le lien d'accès ci-dessous. Ils doivent accéder au lien pour accepter l'invitation.",
|
||||
"inviteSentDescription": "L'utilisateur a été invité. Ils doivent accéder au lien ci-dessous pour accepter l'invitation.",
|
||||
"inviteExpiresIn": "L'invitation expirera dans <b>{days, plural, =1 {# jour} other {# jours}}</b>.",
|
||||
"idpTitle": "Fournisseur d'identité",
|
||||
"idpSelect": "Sélectionnez le fournisseur d'identité pour l'utilisateur externe",
|
||||
"idpNotConfigured": "Aucun fournisseur d'identité n'est configuré. Veuillez configurer un fournisseur d'identité avant de créer des utilisateurs externes.",
|
||||
"usernameUniq": "Ceci doit correspondre au nom d'utilisateur unique qui existe dans le fournisseur d'identité sélectionné.",
|
||||
"emailOptional": "E-mail (Optionnel)",
|
||||
"nameOptional": "Nom (Optionnel)",
|
||||
"accessControls": "Contrôles d'accès",
|
||||
"userDescription2": "Gérer les paramètres de cet utilisateur",
|
||||
"accessRoleErrorAdd": "Échec de l'ajout de l'utilisateur au rôle",
|
||||
"accessRoleErrorAddDescription": "Une erreur s'est produite lors de l'ajout de l'utilisateur au rôle.",
|
||||
"userSaved": "Utilisateur enregistré",
|
||||
"userSavedDescription": "L'utilisateur a été mis à jour.",
|
||||
"accessControlsDescription": "Gérer ce que cet utilisateur peut accéder et faire dans l'organisation",
|
||||
"accessControlsSubmit": "Enregistrer les contrôles d'accès",
|
||||
"roles": "Rôles",
|
||||
"accessUsersRoles": "Gérer les utilisateurs et les rôles",
|
||||
"accessUsersRolesDescription": "Invitez des utilisateurs et ajoutez-les aux rôles pour gérer l'accès à votre organisation",
|
||||
"key": "Clé",
|
||||
"createdAt": "Créé le",
|
||||
"proxyErrorInvalidHeader": "Valeur d'en-tête Host personnalisée invalide. Utilisez le format de nom de domaine, ou laissez vide pour désactiver l'en-tête Host personnalisé.",
|
||||
"proxyErrorTls": "Nom de serveur TLS invalide. Utilisez le format de nom de domaine, ou laissez vide pour supprimer le nom de serveur TLS.",
|
||||
"targetErrorFetch": "Échec de la récupération des cibles",
|
||||
"targetErrorFetchDescription": "Une erreur s'est produite lors de la récupération des cibles",
|
||||
"siteErrorFetch": "Échec de la récupération de la ressource",
|
||||
"siteErrorFetchDescription": "Une erreur s'est produite lors de la récupération de la ressource",
|
||||
"targetErrorDuplicate": "Cible en double",
|
||||
"targetErrorDuplicateDescription": "Une cible avec ces paramètres existe déjà",
|
||||
"targetWireGuardErrorInvalidIp": "IP cible invalide",
|
||||
"targetWireGuardErrorInvalidIpDescription": "L'IP cible doit être dans le sous-réseau du site",
|
||||
"targetsUpdated": "Cibles mises à jour",
|
||||
"targetsUpdatedDescription": "Cibles et paramètres mis à jour avec succès",
|
||||
"targetsErrorUpdate": "Échec de la mise à jour des cibles",
|
||||
"targetsErrorUpdateDescription": "Une erreur s'est produite lors de la mise à jour des cibles",
|
||||
"targetTlsUpdate": "Paramètres TLS mis à jour",
|
||||
"targetTlsUpdateDescription": "Vos paramètres TLS ont été mis à jour avec succès",
|
||||
"targetErrorTlsUpdate": "Échec de la mise à jour des paramètres TLS",
|
||||
"targetErrorTlsUpdateDescription": "Une erreur s'est produite lors de la mise à jour des paramètres TLS",
|
||||
"proxyUpdated": "Paramètres du proxy mis à jour",
|
||||
"proxyUpdatedDescription": "Vos paramètres de proxy ont été mis à jour avec succès",
|
||||
"proxyErrorUpdate": "Échec de la mise à jour des paramètres du proxy",
|
||||
"proxyErrorUpdateDescription": "Une erreur s'est produite lors de la mise à jour des paramètres du proxy",
|
||||
"targetAddr": "IP / Nom d'hôte",
|
||||
"targetPort": "Port",
|
||||
"targetProtocol": "Protocole",
|
||||
"targetTlsSettings": "Paramètres HTTPS & TLS",
|
||||
"targetTlsSettingsDescription": "Configurer les paramètres TLS pour votre ressource",
|
||||
"targetTlsSettingsAdvanced": "Paramètres TLS avancés",
|
||||
"targetTlsSni": "Nom de serveur TLS (SNI)",
|
||||
"targetTlsSniDescription": "Le nom de serveur TLS à utiliser pour SNI. Laissez vide pour utiliser la valeur par défaut.",
|
||||
"targetTlsSubmit": "Enregistrer les paramètres",
|
||||
"targets": "Configuration des cibles",
|
||||
"targetsDescription": "Configurez les cibles pour router le trafic vers vos services",
|
||||
"targetStickySessions": "Activer les sessions persistantes",
|
||||
"targetStickySessionsDescription": "Maintenir les connexions sur la même cible backend pendant toute leur session.",
|
||||
"methodSelect": "Sélectionner la méthode",
|
||||
"targetSubmit": "Ajouter une cible",
|
||||
"targetNoOne": "Aucune cible. Ajoutez une cible en utilisant le formulaire.",
|
||||
"targetNoOneDescription": "L'ajout de plus d'une cible ci-dessus activera l'équilibrage de charge.",
|
||||
"targetsSubmit": "Enregistrer les cibles",
|
||||
"proxyAdditional": "Paramètres de proxy supplémentaires",
|
||||
"proxyAdditionalDescription": "Configurer la façon dont votre ressource gère les paramètres de proxy",
|
||||
"proxyCustomHeader": "En-tête Host personnalisé",
|
||||
"proxyCustomHeaderDescription": "L'en-tête host à définir lors du proxy des requêtes. Laissez vide pour utiliser la valeur par défaut.",
|
||||
"proxyAdditionalSubmit": "Enregistrer les paramètres de proxy",
|
||||
"subnetMaskErrorInvalid": "Masque de sous-réseau invalide. Doit être entre 0 et 32.",
|
||||
"ipAddressErrorInvalidFormat": "Format d'adresse IP invalide",
|
||||
"ipAddressErrorInvalidOctet": "Octet d'adresse IP invalide",
|
||||
"path": "Chemin",
|
||||
"ipAddressRange": "Plage IP",
|
||||
"rulesErrorFetch": "Échec de la récupération des règles",
|
||||
"rulesErrorFetchDescription": "Une erreur s'est produite lors de la récupération des règles",
|
||||
"rulesErrorDuplicate": "Règle en double",
|
||||
"rulesErrorDuplicateDescription": "Une règle avec ces paramètres existe déjà",
|
||||
"rulesErrorInvalidIpAddressRange": "CIDR invalide",
|
||||
"rulesErrorInvalidIpAddressRangeDescription": "Veuillez entrer une valeur CIDR valide",
|
||||
"rulesErrorInvalidUrl": "Chemin URL invalide",
|
||||
"rulesErrorInvalidUrlDescription": "Veuillez entrer un chemin URL valide",
|
||||
"rulesErrorInvalidIpAddress": "IP invalide",
|
||||
"rulesErrorInvalidIpAddressDescription": "Veuillez entrer une adresse IP valide",
|
||||
"rulesErrorUpdate": "Échec de la mise à jour des règles",
|
||||
"rulesErrorUpdateDescription": "Une erreur s'est produite lors de la mise à jour des règles",
|
||||
"rulesUpdated": "Activer les règles",
|
||||
"rulesUpdatedDescription": "L'évaluation des règles a été mise à jour",
|
||||
"rulesMatchIpAddressRangeDescription": "Entrez une adresse au format CIDR (ex: 103.21.244.0/22)",
|
||||
"rulesMatchIpAddress": "Entrez une adresse IP (ex: 103.21.244.12)",
|
||||
"rulesMatchUrl": "Entrez un chemin URL ou un motif (ex: /api/v1/todos ou /api/v1/*)",
|
||||
"rulesErrorInvalidPriority": "Priorité invalide",
|
||||
"rulesErrorInvalidPriorityDescription": "Veuillez entrer une priorité valide",
|
||||
"rulesErrorDuplicatePriority": "Priorités en double",
|
||||
"rulesErrorDuplicatePriorityDescription": "Veuillez entrer des priorités uniques",
|
||||
"ruleUpdated": "Règles mises à jour",
|
||||
"ruleUpdatedDescription": "Règles mises à jour avec succès",
|
||||
"ruleErrorUpdate": "L'opération a échoué",
|
||||
"ruleErrorUpdateDescription": "Une erreur s'est produite lors de l'enregistrement",
|
||||
"rulesPriority": "Priorité",
|
||||
"rulesAction": "Action",
|
||||
"rulesMatchType": "Type de correspondance",
|
||||
"value": "Valeur",
|
||||
"rulesAbout": "À propos des règles",
|
||||
"rulesAboutDescription": "Les règles vous permettent de contrôler l'accès à votre ressource en fonction d'un ensemble de critères. Vous pouvez créer des règles pour autoriser ou refuser l'accès basé sur l'adresse IP ou le chemin URL.",
|
||||
"rulesActions": "Actions",
|
||||
"rulesActionAlwaysAllow": "Toujours autoriser : Contourner toutes les méthodes d'authentification",
|
||||
"rulesActionAlwaysDeny": "Toujours refuser : Bloquer toutes les requêtes ; aucune authentification ne peut être tentée",
|
||||
"rulesMatchCriteria": "Critères de correspondance",
|
||||
"rulesMatchCriteriaIpAddress": "Correspondre à une adresse IP spécifique",
|
||||
"rulesMatchCriteriaIpAddressRange": "Correspondre à une plage d'adresses IP en notation CIDR",
|
||||
"rulesMatchCriteriaUrl": "Correspondre à un chemin URL ou un motif",
|
||||
"rulesEnable": "Activer les règles",
|
||||
"rulesEnableDescription": "Activer ou désactiver l'évaluation des règles pour cette ressource",
|
||||
"rulesResource": "Configuration des règles de ressource",
|
||||
"rulesResourceDescription": "Configurer les règles pour contrôler l'accès à votre ressource",
|
||||
"ruleSubmit": "Ajouter une règle",
|
||||
"rulesNoOne": "Aucune règle. Ajoutez une règle en utilisant le formulaire.",
|
||||
"rulesOrder": "Les règles sont évaluées par priorité dans l'ordre croissant.",
|
||||
"rulesSubmit": "Enregistrer les règles",
|
||||
"resourceErrorCreate": "Erreur lors de la création de la ressource",
|
||||
"resourceErrorCreateDescription": "Une erreur s'est produite lors de la création de la ressource",
|
||||
"resourceErrorCreateMessage": "Erreur lors de la création de la ressource :",
|
||||
"resourceErrorCreateMessageDescription": "Une erreur inattendue s'est produite",
|
||||
"sitesErrorFetch": "Erreur lors de la récupération des sites",
|
||||
"sitesErrorFetchDescription": "Une erreur s'est produite lors de la récupération des sites",
|
||||
"domainsErrorFetch": "Erreur lors de la récupération des domaines",
|
||||
"domainsErrorFetchDescription": "Une erreur s'est produite lors de la récupération des domaines",
|
||||
"none": "Aucun",
|
||||
"unknown": "Inconnu",
|
||||
"resources": "Ressources",
|
||||
"resourcesDescription": "Les ressources sont des proxys vers des applications exécutées sur votre réseau privé. Créez une ressource pour tout service HTTP/HTTPS ou TCP/UDP brut sur votre réseau privé. Chaque ressource doit être connectée à un site pour permettre une connectivité privée et sécurisée via un tunnel WireGuard chiffré.",
|
||||
"resourcesWireGuardConnect": "Connectivité sécurisée avec chiffrement WireGuard",
|
||||
"resourcesMultipleAuthenticationMethods": "Configurer plusieurs méthodes d'authentification",
|
||||
"resourcesUsersRolesAccess": "Contrôle d'accès basé sur les utilisateurs et les rôles",
|
||||
"resourcesErrorUpdate": "Échec de la bascule de la ressource",
|
||||
"resourcesErrorUpdateDescription": "Une erreur s'est produite lors de la mise à jour de la ressource",
|
||||
"access": "Accès",
|
||||
"shareLink": "Lien de partage {resource}",
|
||||
"resourceSelect": "Sélectionner une ressource",
|
||||
"shareLinks": "Liens de partage",
|
||||
"share": "Liens partageables",
|
||||
"shareDescription2": "Créez des liens partageables vers vos ressources. Les liens fournissent un accès temporaire ou illimité à votre ressource. Vous pouvez configurer la durée d'expiration du lien lors de sa création.",
|
||||
"shareEasyCreate": "Facile à créer et à partager",
|
||||
"shareConfigurableExpirationDuration": "Durée d'expiration configurable",
|
||||
"shareSecureAndRevocable": "Sécurisé et révocable",
|
||||
"nameMin": "Le nom doit contenir au moins {len} caractères.",
|
||||
"nameMax": "Le nom ne doit pas dépasser {len} caractères.",
|
||||
"sitesConfirmCopy": "Veuillez confirmer que vous avez copié la configuration.",
|
||||
"unknownCommand": "Commande inconnue",
|
||||
"newtErrorFetchReleases": "Échec de la récupération des informations de version : {err}",
|
||||
"newtErrorFetchLatest": "Erreur lors de la récupération de la dernière version : {err}",
|
||||
"newtEndpoint": "Point de terminaison Newt",
|
||||
"newtId": "ID Newt",
|
||||
"newtSecretKey": "Clé secrète Newt",
|
||||
"architecture": "Architecture",
|
||||
"sites": "Sites",
|
||||
"siteWgAnyClients": "Utilisez n'importe quel client WireGuard pour vous connecter. Vous devrez adresser vos ressources internes en utilisant l'IP du pair.",
|
||||
"siteWgCompatibleAllClients": "Compatible avec tous les clients WireGuard",
|
||||
"siteWgManualConfigurationRequired": "Configuration manuelle requise",
|
||||
"userErrorNotAdminOrOwner": "L'utilisateur n'est pas un administrateur ou un propriétaire",
|
||||
"pangolinSettings": "Paramètres - Pangolin",
|
||||
"accessRoleYour": "Votre rôle :",
|
||||
"accessRoleSelect2": "Sélectionner un rôle",
|
||||
"accessUserSelect": "Sélectionner un utilisateur",
|
||||
"otpEmailEnter": "Entrer un e-mail",
|
||||
"otpEmailEnterDescription": "Appuyez sur Entrée pour ajouter un e-mail après l'avoir saisi dans le champ.",
|
||||
"otpEmailErrorInvalid": "Adresse e-mail invalide. Le caractère générique (*) doit être la partie locale entière.",
|
||||
"otpEmailSmtpRequired": "SMTP requis",
|
||||
"otpEmailSmtpRequiredDescription": "Le SMTP doit être activé sur le serveur pour utiliser l'authentification par mot de passe à usage unique.",
|
||||
"otpEmailTitle": "Mots de passe à usage unique",
|
||||
"otpEmailTitleDescription": "Exiger une authentification par e-mail pour l'accès aux ressources",
|
||||
"otpEmailWhitelist": "Liste blanche des e-mails",
|
||||
"otpEmailWhitelistList": "E-mails sur liste blanche",
|
||||
"otpEmailWhitelistListDescription": "Seuls les utilisateurs avec ces adresses e-mail pourront accéder à cette ressource. Ils devront saisir un mot de passe à usage unique envoyé à leur e-mail. Les caractères génériques (*@example.com) peuvent être utilisés pour autoriser n'importe quelle adresse e-mail d'un domaine.",
|
||||
"otpEmailWhitelistSave": "Enregistrer la liste blanche",
|
||||
"passwordAdd": "Ajouter un mot de passe",
|
||||
"passwordRemove": "Supprimer le mot de passe",
|
||||
"pincodeAdd": "Ajouter un code PIN",
|
||||
"pincodeRemove": "Supprimer le code PIN",
|
||||
"resourceAuthMethods": "Méthodes d'authentification",
|
||||
"resourceAuthMethodsDescriptions": "Permettre l'accès à la ressource via des méthodes d'authentification supplémentaires",
|
||||
"resourceAuthSettingsSave": "Enregistré avec succès",
|
||||
"resourceAuthSettingsSaveDescription": "Les paramètres d'authentification ont été enregistrés",
|
||||
"resourceErrorAuthFetch": "Échec de la récupération des données",
|
||||
"resourceErrorAuthFetchDescription": "Une erreur s'est produite lors de la récupération des données",
|
||||
"resourceErrorPasswordRemove": "Erreur lors de la suppression du mot de passe de la ressource",
|
||||
"resourceErrorPasswordRemoveDescription": "Une erreur s'est produite lors de la suppression du mot de passe de la ressource",
|
||||
"resourceErrorPasswordSetup": "Erreur lors de la configuration du mot de passe de la ressource",
|
||||
"resourceErrorPasswordSetupDescription": "Une erreur s'est produite lors de la configuration du mot de passe de la ressource",
|
||||
"resourceErrorPincodeRemove": "Erreur lors de la suppression du code PIN de la ressource",
|
||||
"resourceErrorPincodeRemoveDescription": "Une erreur s'est produite lors de la suppression du code PIN de la ressource",
|
||||
"resourceErrorPincodeSetup": "Erreur lors de la configuration du code PIN de la ressource",
|
||||
"resourceErrorPincodeSetupDescription": "Une erreur s'est produite lors de la configuration du code PIN de la ressource",
|
||||
"resourceErrorUsersRolesSave": "Échec de la définition des rôles",
|
||||
"resourceErrorUsersRolesSaveDescription": "Une erreur s'est produite lors de la définition des rôles",
|
||||
"resourceErrorWhitelistSave": "Échec de l'enregistrement de la liste blanche",
|
||||
"resourceErrorWhitelistSaveDescription": "Une erreur s'est produite lors de l'enregistrement de la liste blanche",
|
||||
"resourcePasswordSubmit": "Activer la protection par mot de passe",
|
||||
"resourcePasswordRemove": "Mot de passe de la ressource supprimé",
|
||||
"resourcePasswordRemoveDescription": "Le mot de passe de la ressource a été supprimé avec succès",
|
||||
"resourcePasswordSetup": "Mot de passe de la ressource défini",
|
||||
"resourcePasswordSetupDescription": "Le mot de passe de la ressource a été défini avec succès",
|
||||
"resourcePasswordSetupTitle": "Définir le mot de passe",
|
||||
"resourcePasswordSetupTitleDescription": "Définir un mot de passe pour protéger cette ressource",
|
||||
"resourcePincode": "Code PIN",
|
||||
"resourcePincodeSubmit": "Activer la protection par code PIN",
|
||||
"resourcePincodeProtection": "Protection par code PIN {status}",
|
||||
"resourcePincodeRemove": "Code PIN de la ressource supprimé",
|
||||
"resourcePincodeRemoveDescription": "Le code PIN de la ressource a été supprimé avec succès",
|
||||
"resourcePincodeSetup": "Code PIN de la ressource défini",
|
||||
"resourcePincodeSetupDescription": "Le code PIN de la ressource a été défini avec succès",
|
||||
"resourcePincodeSetupTitle": "Définir le code PIN",
|
||||
"resourcePincodeSetupTitleDescription": "Définir un code PIN pour protéger cette ressource",
|
||||
"resourceRoleDescription": "Les administrateurs peuvent toujours accéder à cette ressource.",
|
||||
"resourceUsersRoles": "Utilisateurs et rôles",
|
||||
"resourceUsersRolesDescription": "Configurer quels utilisateurs et rôles peuvent visiter cette ressource",
|
||||
"resourceUsersRolesSubmit": "Enregistrer les utilisateurs et les rôles",
|
||||
"resourceWhitelistSave": "Enregistré avec succès",
|
||||
"resourceWhitelistSaveDescription": "Les paramètres de la liste blanche ont été enregistrés",
|
||||
"ssoUse": "Utiliser la SSO de la plateforme",
|
||||
"ssoUseDescription": "Les utilisateurs existants n'auront à se connecter qu'une seule fois pour toutes les ressources qui ont cette option activée.",
|
||||
"proxyErrorInvalidPort": "Numéro de port invalide",
|
||||
"subdomainErrorInvalid": "Sous-domaine invalide",
|
||||
"domainErrorFetch": "Erreur lors de la récupération des domaines",
|
||||
"domainErrorFetchDescription": "Une erreur s'est produite lors de la récupération des domaines",
|
||||
"resourceErrorUpdate": "Échec de la mise à jour de la ressource",
|
||||
"resourceErrorUpdateDescription": "Une erreur s'est produite lors de la mise à jour de la ressource",
|
||||
"resourceUpdated": "Ressource mise à jour",
|
||||
"resourceUpdatedDescription": "La ressource a été mise à jour avec succès",
|
||||
"resourceErrorTransfer": "Échec du transfert de la ressource",
|
||||
"resourceErrorTransferDescription": "Une erreur s'est produite lors du transfert de la ressource",
|
||||
"resourceTransferred": "Ressource transférée",
|
||||
"resourceTransferredDescription": "La ressource a été transférée avec succès",
|
||||
"resourceErrorToggle": "Échec de la modification de l'état de la ressource",
|
||||
"resourceErrorToggleDescription": "Une erreur s'est produite lors de la mise à jour de la ressource",
|
||||
"resourceVisibilityTitle": "Visibilité",
|
||||
"resourceVisibilityTitleDescription": "Activer ou désactiver complètement la visibilité de la ressource",
|
||||
"resourceGeneral": "Paramètres généraux",
|
||||
"resourceGeneralDescription": "Configurer les paramètres généraux de cette ressource",
|
||||
"resourceEnable": "Activer la ressource",
|
||||
"resourceTransfer": "Transférer la ressource",
|
||||
"resourceTransferDescription": "Transférer cette ressource vers un autre site",
|
||||
"resourceTransferSubmit": "Transférer la ressource",
|
||||
"siteDestination": "Site de destination",
|
||||
"searchSites": "Rechercher des sites",
|
||||
"accessRoleCreate": "Créer un rôle",
|
||||
"accessRoleCreateDescription": "Créer un nouveau rôle pour regrouper les utilisateurs et gérer leurs permissions.",
|
||||
"accessRoleCreateSubmit": "Créer un rôle",
|
||||
"accessRoleCreated": "Rôle créé",
|
||||
"accessRoleCreatedDescription": "Le rôle a été créé avec succès.",
|
||||
"accessRoleErrorCreate": "Échec de la création du rôle",
|
||||
"accessRoleErrorCreateDescription": "Une erreur s'est produite lors de la création du rôle.",
|
||||
"accessRoleErrorNewRequired": "Un nouveau rôle est requis",
|
||||
"accessRoleErrorRemove": "Échec de la suppression du rôle",
|
||||
"accessRoleErrorRemoveDescription": "Une erreur s'est produite lors de la suppression du rôle.",
|
||||
"accessRoleName": "Nom du rôle",
|
||||
"accessRoleQuestionRemove": "Vous êtes sur le point de supprimer le rôle <b>{name}</b>. Cette action est irréversible.",
|
||||
"accessRoleRemove": "Supprimer le rôle",
|
||||
"accessRoleRemoveDescription": "Retirer un rôle de l'organisation",
|
||||
"accessRoleRemoveSubmit": "Supprimer le rôle",
|
||||
"accessRoleRemoved": "Rôle supprimé",
|
||||
"accessRoleRemovedDescription": "Le rôle a été supprimé avec succès.",
|
||||
"accessRoleRequiredRemove": "Avant de supprimer ce rôle, veuillez sélectionner un nouveau rôle pour transférer les membres existants.",
|
||||
"manage": "Gérer",
|
||||
"sitesNotFound": "Aucun site trouvé."
|
||||
}
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
"siteCreateDescription2": "Segui i passaggi qui sotto per creare e collegare un nuovo sito",
|
||||
"siteCreateDescription": "Crea un nuovo sito per iniziare a connettere le tue risorse",
|
||||
"close": "Chiudi",
|
||||
"siteNameMin": "Il nome deve contenere almeno 2 caratteri.",
|
||||
"siteNameMax": "Il nome non deve essere più lungo di 30 caratteri.",
|
||||
"siteErrorCreate": "Errore nella creazione del sito",
|
||||
"siteErrorCreateKeyPair": "Coppia di chiavi o valori predefiniti del sito non trovati",
|
||||
"siteErrorCreateDefaults": "Predefiniti del sito non trovati",
|
||||
|
@ -71,7 +69,7 @@
|
|||
"dockerRun": "Corsa Docker",
|
||||
"siteLearnLocal": "I siti locali non tunnel, saperne di più",
|
||||
"siteConfirmCopy": "Ho copiato la configurazione",
|
||||
"searchSites": "Cerca siti...",
|
||||
"searchSitesProgress": "Cerca siti...",
|
||||
"siteAdd": "Aggiungi Sito",
|
||||
"siteInstallNewt": "Installa Newt",
|
||||
"siteInstallNewtDescription": "Get Newt running on your system",
|
||||
|
@ -111,7 +109,7 @@
|
|||
"shareErrorDelete": "Impossibile eliminare il link",
|
||||
"shareErrorDeleteMessage": "Si è verificato un errore durante l'eliminazione del link",
|
||||
"shareDeleted": "Link eliminato",
|
||||
"shareDeletedDesciption": "Il link è stato eliminato",
|
||||
"shareDeletedDescription": "Il link è stato eliminato",
|
||||
"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",
|
||||
"usageExamples": "Esempi Di Utilizzo",
|
||||
|
@ -234,7 +232,7 @@
|
|||
"username": "Username",
|
||||
"identityProvider": "Provider Di Identità",
|
||||
"role": "Ruolo",
|
||||
"accessRoleNameRequired": "Il nome è obbligatorio",
|
||||
"nameRequired": "Il nome è obbligatorio",
|
||||
"accessRolesManage": "Gestisci Ruoli",
|
||||
"accessRolesDescription": "Configura i ruoli per gestire l'accesso alla tua organizzazione",
|
||||
"accessRolesSearch": "Ricerca ruoli...",
|
||||
|
@ -252,8 +250,6 @@
|
|||
"years": "Anni",
|
||||
"day": "{count, plural, =1 {# giorno} other {# giorni}}",
|
||||
"apiKeysTitle": "Informazioni Chiave API",
|
||||
"apiKeysNameMin": "Il nome deve contenere almeno 2 caratteri.",
|
||||
"apiKeysNameMax": "Il nome non deve essere più lungo di 255 caratteri.",
|
||||
"apiKeysConfirmCopy2": "Devi confermare di aver copiato la chiave API.",
|
||||
"apiKeysErrorCreate": "Errore nella creazione della chiave API",
|
||||
"apiKeysErrorSetPermission": "Errore nell'impostazione dei permessi",
|
||||
|
@ -382,5 +378,319 @@
|
|||
"inviteValidityPeriodSelect": "Seleziona periodo di validità",
|
||||
"inviteRegenerateMessage": "L'invito è stato rigenerato. L'utente deve accedere al link qui sotto per accettare l'invito.",
|
||||
"inviteRegenerateButton": "Rigenera",
|
||||
"expiresAt": "Scade Il"
|
||||
"expiresAt": "Scade Il",
|
||||
"accessRoleUnknown": "Ruolo Sconosciuto",
|
||||
"placeholder": "Segnaposto",
|
||||
"userErrorOrgRemove": "Impossibile rimuovere l'utente",
|
||||
"userErrorOrgRemoveDescription": "Si è verificato un errore durante la rimozione dell'utente.",
|
||||
"userOrgRemoved": "Utente rimosso",
|
||||
"userOrgRemovedDescription": "L'utente {email} è stato rimosso dall'organizzazione.",
|
||||
"userQuestionOrgRemove": "Sei sicuro di voler rimuovere <b>{email}</b> dall'organizzazione?",
|
||||
"userMessageOrgRemove": "Una volta rimosso, questo utente non avrà più accesso all'organizzazione. Puoi sempre reinvitarlo in seguito, ma dovrà accettare nuovamente l'invito.",
|
||||
"userMessageOrgConfirm": "Per confermare, digita il nome dell'utente qui sotto.",
|
||||
"userRemoveOrgConfirm": "Conferma Rimozione Utente",
|
||||
"userRemoveOrg": "Rimuovi Utente dall'Organizzazione",
|
||||
"users": "Utenti",
|
||||
"accessRoleMember": "Membro",
|
||||
"accessRoleOwner": "Proprietario",
|
||||
"userConfirmed": "Confermato",
|
||||
"idpNameInternal": "Interno",
|
||||
"emailInvalid": "Indirizzo email non valido",
|
||||
"inviteValidityDuration": "Seleziona una durata",
|
||||
"accessRoleSelectPlease": "Seleziona un ruolo",
|
||||
"usernameRequired": "Username richiesto",
|
||||
"idpSelectPlease": "Seleziona un provider di identità",
|
||||
"idpGenericOidc": "Provider OAuth2/OIDC generico.",
|
||||
"accessRoleErrorFetch": "Impossibile recuperare i ruoli",
|
||||
"accessRoleErrorFetchDescription": "Si è verificato un errore durante il recupero dei ruoli",
|
||||
"idpErrorFetch": "Impossibile recuperare i provider di identità",
|
||||
"idpErrorFetchDescription": "Si è verificato un errore durante il recupero dei provider di identità",
|
||||
"userErrorExists": "Utente Già Esistente",
|
||||
"userErrorExistsDescription": "Questo utente è già membro dell'organizzazione.",
|
||||
"inviteError": "Impossibile invitare l'utente",
|
||||
"inviteErrorDescription": "Si è verificato un errore durante l'invito dell'utente",
|
||||
"userInvited": "Utente invitato",
|
||||
"userInvitedDescription": "L'utente è stato invitato con successo.",
|
||||
"userErrorCreate": "Impossibile creare l'utente",
|
||||
"userErrorCreateDescription": "Si è verificato un errore durante la creazione dell'utente",
|
||||
"userCreated": "Utente creato",
|
||||
"userCreatedDescription": "L'utente è stato creato con successo.",
|
||||
"userTypeInternal": "Utente Interno",
|
||||
"userTypeInternalDescription": "Invita un utente a unirsi direttamente alla tua organizzazione.",
|
||||
"userTypeExternal": "Utente Esterno",
|
||||
"userTypeExternalDescription": "Crea un utente con un provider di identità esterno.",
|
||||
"accessUserCreateDescription": "Segui i passaggi seguenti per creare un nuovo utente",
|
||||
"userSeeAll": "Vedi Tutti gli Utenti",
|
||||
"userTypeTitle": "Tipo di Utente",
|
||||
"userTypeDescription": "Determina come vuoi creare l'utente",
|
||||
"userSettings": "Informazioni Utente",
|
||||
"userSettingsDescription": "Inserisci i dettagli per il nuovo utente",
|
||||
"inviteEmailSent": "Invia email di invito all'utente",
|
||||
"inviteValid": "Valido Per",
|
||||
"selectDuration": "Seleziona durata",
|
||||
"accessRoleSelect": "Seleziona ruolo",
|
||||
"inviteEmailSentDescription": "È stata inviata un'email all'utente con il link di accesso qui sotto. Devono accedere al link per accettare l'invito.",
|
||||
"inviteSentDescription": "L'utente è stato invitato. Deve accedere al link qui sotto per accettare l'invito.",
|
||||
"inviteExpiresIn": "L'invito scadrà tra <b>{days, plural, =1 {# giorno} other {# giorni}}</b>.",
|
||||
"idpTitle": "Provider di Identità",
|
||||
"idpSelect": "Seleziona il provider di identità per l'utente esterno",
|
||||
"idpNotConfigured": "Nessun provider di identità configurato. Configura un provider di identità prima di creare utenti esterni.",
|
||||
"usernameUniq": "Questo deve corrispondere all'username univoco esistente nel provider di identità selezionato.",
|
||||
"emailOptional": "Email (Opzionale)",
|
||||
"nameOptional": "Nome (Opzionale)",
|
||||
"accessControls": "Controlli di Accesso",
|
||||
"userDescription2": "Gestisci le impostazioni di questo utente",
|
||||
"accessRoleErrorAdd": "Impossibile aggiungere l'utente al ruolo",
|
||||
"accessRoleErrorAddDescription": "Si è verificato un errore durante l'aggiunta dell'utente al ruolo.",
|
||||
"userSaved": "Utente salvato",
|
||||
"userSavedDescription": "L'utente è stato aggiornato.",
|
||||
"accessControlsDescription": "Gestisci cosa questo utente può accedere e fare nell'organizzazione",
|
||||
"accessControlsSubmit": "Salva Controlli di Accesso",
|
||||
"roles": "Ruoli",
|
||||
"accessUsersRoles": "Gestisci Utenti e Ruoli",
|
||||
"accessUsersRolesDescription": "Invita utenti e aggiungili ai ruoli per gestire l'accesso alla tua organizzazione",
|
||||
"key": "Chiave",
|
||||
"createdAt": "Creato Il",
|
||||
"proxyErrorInvalidHeader": "Valore dell'intestazione Host personalizzata non valido. Usa il formato nome dominio o salva vuoto per rimuovere l'intestazione Host personalizzata.",
|
||||
"proxyErrorTls": "Nome Server TLS non valido. Usa il formato nome dominio o salva vuoto per rimuovere il Nome Server TLS.",
|
||||
"targetErrorFetch": "Impossibile recuperare i target",
|
||||
"targetErrorFetchDescription": "Si è verificato un errore durante il recupero dei target",
|
||||
"siteErrorFetch": "Impossibile recuperare la risorsa",
|
||||
"siteErrorFetchDescription": "Si è verificato un errore durante il recupero della risorsa",
|
||||
"targetErrorDuplicate": "Target duplicato",
|
||||
"targetErrorDuplicateDescription": "Esiste già un target con queste impostazioni",
|
||||
"targetWireGuardErrorInvalidIp": "IP target non valido",
|
||||
"targetWireGuardErrorInvalidIpDescription": "L'IP target deve essere all'interno della subnet del sito",
|
||||
"targetsUpdated": "Target aggiornati",
|
||||
"targetsUpdatedDescription": "Target e impostazioni aggiornati con successo",
|
||||
"targetsErrorUpdate": "Impossibile aggiornare i target",
|
||||
"targetsErrorUpdateDescription": "Si è verificato un errore durante l'aggiornamento dei target",
|
||||
"targetTlsUpdate": "Impostazioni TLS aggiornate",
|
||||
"targetTlsUpdateDescription": "Le tue impostazioni TLS sono state aggiornate con successo",
|
||||
"targetErrorTlsUpdate": "Impossibile aggiornare le impostazioni TLS",
|
||||
"targetErrorTlsUpdateDescription": "Si è verificato un errore durante l'aggiornamento delle impostazioni TLS",
|
||||
"proxyUpdated": "Impostazioni proxy aggiornate",
|
||||
"proxyUpdatedDescription": "Le tue impostazioni proxy sono state aggiornate con successo",
|
||||
"proxyErrorUpdate": "Impossibile aggiornare le impostazioni proxy",
|
||||
"proxyErrorUpdateDescription": "Si è verificato un errore durante l'aggiornamento delle impostazioni proxy",
|
||||
"targetAddr": "IP / Nome host",
|
||||
"targetPort": "Porta",
|
||||
"targetProtocol": "Protocollo",
|
||||
"targetTlsSettings": "Impostazioni HTTPS e TLS",
|
||||
"targetTlsSettingsDescription": "Configura le impostazioni TLS per la tua risorsa",
|
||||
"targetTlsSettingsAdvanced": "Impostazioni TLS Avanzate",
|
||||
"targetTlsSni": "Nome Server TLS (SNI)",
|
||||
"targetTlsSniDescription": "Il Nome Server TLS da usare per SNI. Lascia vuoto per usare quello predefinito.",
|
||||
"targetTlsSubmit": "Salva Impostazioni",
|
||||
"targets": "Configurazione Target",
|
||||
"targetsDescription": "Configura i target per instradare il traffico ai tuoi servizi",
|
||||
"targetStickySessions": "Abilita Sessioni Persistenti",
|
||||
"targetStickySessionsDescription": "Mantieni le connessioni sullo stesso target backend per l'intera sessione.",
|
||||
"methodSelect": "Seleziona metodo",
|
||||
"targetSubmit": "Aggiungi Target",
|
||||
"targetNoOne": "Nessun target. Aggiungi un target usando il modulo.",
|
||||
"targetNoOneDescription": "L'aggiunta di più di un target abiliterà il bilanciamento del carico.",
|
||||
"targetsSubmit": "Salva Target",
|
||||
"proxyAdditional": "Impostazioni Proxy Aggiuntive",
|
||||
"proxyAdditionalDescription": "Configura come la tua risorsa gestisce le impostazioni proxy",
|
||||
"proxyCustomHeader": "Intestazione Host Personalizzata",
|
||||
"proxyCustomHeaderDescription": "L'intestazione host da impostare durante il proxy delle richieste. Lascia vuoto per usare quella predefinita.",
|
||||
"proxyAdditionalSubmit": "Salva Impostazioni Proxy",
|
||||
"subnetMaskErrorInvalid": "Maschera di sottorete non valida. Deve essere tra 0 e 32.",
|
||||
"ipAddressErrorInvalidFormat": "Formato indirizzo IP non valido",
|
||||
"ipAddressErrorInvalidOctet": "Ottetto indirizzo IP non valido",
|
||||
"path": "Percorso",
|
||||
"ipAddressRange": "Intervallo IP",
|
||||
"rulesErrorFetch": "Impossibile recuperare le regole",
|
||||
"rulesErrorFetchDescription": "Si è verificato un errore durante il recupero delle regole",
|
||||
"rulesErrorDuplicate": "Regola duplicata",
|
||||
"rulesErrorDuplicateDescription": "Esiste già una regola con queste impostazioni",
|
||||
"rulesErrorInvalidIpAddressRange": "CIDR non valido",
|
||||
"rulesErrorInvalidIpAddressRangeDescription": "Inserisci un valore CIDR valido",
|
||||
"rulesErrorInvalidUrl": "Percorso URL non valido",
|
||||
"rulesErrorInvalidUrlDescription": "Inserisci un valore di percorso URL valido",
|
||||
"rulesErrorInvalidIpAddress": "IP non valido",
|
||||
"rulesErrorInvalidIpAddressDescription": "Inserisci un indirizzo IP valido",
|
||||
"rulesErrorUpdate": "Impossibile aggiornare le regole",
|
||||
"rulesErrorUpdateDescription": "Si è verificato un errore durante l'aggiornamento delle regole",
|
||||
"rulesUpdated": "Abilita Regole",
|
||||
"rulesUpdatedDescription": "La valutazione delle regole è stata aggiornata",
|
||||
"rulesMatchIpAddressRangeDescription": "Inserisci un indirizzo in formato CIDR (es. 103.21.244.0/22)",
|
||||
"rulesMatchIpAddress": "Inserisci un indirizzo IP (es. 103.21.244.12)",
|
||||
"rulesMatchUrl": "Inserisci un percorso URL o pattern (es. /api/v1/todos o /api/v1/*)",
|
||||
"rulesErrorInvalidPriority": "Priorità Non Valida",
|
||||
"rulesErrorInvalidPriorityDescription": "Inserisci una priorità valida",
|
||||
"rulesErrorDuplicatePriority": "Priorità Duplicate",
|
||||
"rulesErrorDuplicatePriorityDescription": "Inserisci priorità uniche",
|
||||
"ruleUpdated": "Regole aggiornate",
|
||||
"ruleUpdatedDescription": "Regole aggiornate con successo",
|
||||
"ruleErrorUpdate": "Operazione fallita",
|
||||
"ruleErrorUpdateDescription": "Si è verificato un errore durante il salvataggio",
|
||||
"rulesPriority": "Priorità",
|
||||
"rulesAction": "Azione",
|
||||
"rulesMatchType": "Tipo di Corrispondenza",
|
||||
"value": "Valore",
|
||||
"rulesAbout": "Informazioni sulle Regole",
|
||||
"rulesAboutDescription": "Le regole ti permettono di controllare l'accesso alla tua risorsa in base a una serie di criteri. Puoi creare regole per consentire o negare l'accesso basato su indirizzo IP o percorso URL.",
|
||||
"rulesActions": "Azioni",
|
||||
"rulesActionAlwaysAllow": "Consenti Sempre: Ignora tutti i metodi di autenticazione",
|
||||
"rulesActionAlwaysDeny": "Nega Sempre: Blocca tutte le richieste; nessuna autenticazione può essere tentata",
|
||||
"rulesMatchCriteria": "Criteri di Corrispondenza",
|
||||
"rulesMatchCriteriaIpAddress": "Corrisponde a un indirizzo IP specifico",
|
||||
"rulesMatchCriteriaIpAddressRange": "Corrisponde a un intervallo di indirizzi IP in notazione CIDR",
|
||||
"rulesMatchCriteriaUrl": "Corrisponde a un percorso URL o pattern",
|
||||
"rulesEnable": "Abilita Regole",
|
||||
"rulesEnableDescription": "Abilita o disabilita la valutazione delle regole per questa risorsa",
|
||||
"rulesResource": "Configurazione Regole Risorsa",
|
||||
"rulesResourceDescription": "Configura le regole per controllare l'accesso alla tua risorsa",
|
||||
"ruleSubmit": "Aggiungi Regola",
|
||||
"rulesNoOne": "Nessuna regola. Aggiungi una regola usando il modulo.",
|
||||
"rulesOrder": "Le regole sono valutate per priorità in ordine crescente.",
|
||||
"rulesSubmit": "Salva Regole",
|
||||
"resourceErrorCreate": "Errore nella creazione della risorsa",
|
||||
"resourceErrorCreateDescription": "Si è verificato un errore durante la creazione della risorsa",
|
||||
"resourceErrorCreateMessage": "Errore nella creazione della risorsa:",
|
||||
"resourceErrorCreateMessageDescription": "Si è verificato un errore imprevisto",
|
||||
"sitesErrorFetch": "Errore nel recupero dei siti",
|
||||
"sitesErrorFetchDescription": "Si è verificato un errore durante il recupero dei siti",
|
||||
"domainsErrorFetch": "Errore nel recupero dei domini",
|
||||
"domainsErrorFetchDescription": "Si è verificato un errore durante il recupero dei domini",
|
||||
"none": "Nessuno",
|
||||
"unknown": "Sconosciuto",
|
||||
"resources": "Risorse",
|
||||
"resourcesDescription": "Le risorse sono proxy per le applicazioni in esecuzione sulla tua rete privata. Crea una risorsa per qualsiasi servizio HTTP/HTTPS o TCP/UDP raw sulla tua rete privata. Ogni risorsa deve essere collegata a un sito per abilitare la connettività privata e sicura attraverso un tunnel WireGuard crittografato.",
|
||||
"resourcesWireGuardConnect": "Connettività sicura con crittografia WireGuard",
|
||||
"resourcesMultipleAuthenticationMethods": "Configura molteplici metodi di autenticazione",
|
||||
"resourcesUsersRolesAccess": "Controllo accessi basato su utenti e ruoli",
|
||||
"resourcesErrorUpdate": "Impossibile attivare/disattivare la risorsa",
|
||||
"resourcesErrorUpdateDescription": "Si è verificato un errore durante l'aggiornamento della risorsa",
|
||||
"access": "Accesso",
|
||||
"shareLink": "Link di Condivisione {resource}",
|
||||
"resourceSelect": "Seleziona risorsa",
|
||||
"shareLinks": "Link di Condivisione",
|
||||
"share": "Link Condivisibili",
|
||||
"shareDescription2": "Crea link condivisibili per le tue risorse. I link forniscono accesso temporaneo o illimitato alla tua risorsa. Puoi configurare la durata di scadenza del link quando lo crei.",
|
||||
"shareEasyCreate": "Facile da creare e condividere",
|
||||
"shareConfigurableExpirationDuration": "Durata di scadenza configurabile",
|
||||
"shareSecureAndRevocable": "Sicuro e revocabile",
|
||||
"nameMin": "Il nome deve essere di almeno {len} caratteri.",
|
||||
"nameMax": "Il nome non deve superare i {len} caratteri.",
|
||||
"sitesConfirmCopy": "Conferma di aver copiato la configurazione.",
|
||||
"unknownCommand": "Comando sconosciuto",
|
||||
"newtErrorFetchReleases": "Impossibile recuperare le informazioni sulla versione: {err}",
|
||||
"newtErrorFetchLatest": "Errore nel recupero dell'ultima versione: {err}",
|
||||
"newtEndpoint": "Endpoint Newt",
|
||||
"newtId": "ID Newt",
|
||||
"newtSecretKey": "Chiave Segreta Newt",
|
||||
"architecture": "Architettura",
|
||||
"sites": "Siti",
|
||||
"siteWgAnyClients": "Usa qualsiasi client WireGuard per connetterti. Dovrai indirizzare le tue risorse interne usando l'IP del peer.",
|
||||
"siteWgCompatibleAllClients": "Compatibile con tutti i client WireGuard",
|
||||
"siteWgManualConfigurationRequired": "Configurazione manuale richiesta",
|
||||
"userErrorNotAdminOrOwner": "L'utente non è un amministratore o proprietario",
|
||||
"pangolinSettings": "Impostazioni - Pangolin",
|
||||
"accessRoleYour": "Il tuo ruolo:",
|
||||
"accessRoleSelect2": "Seleziona un ruolo",
|
||||
"accessUserSelect": "Seleziona un utente",
|
||||
"otpEmailEnter": "Inserisci un'email",
|
||||
"otpEmailEnterDescription": "Premi invio per aggiungere un'email dopo averla digitata nel campo di input.",
|
||||
"otpEmailErrorInvalid": "Indirizzo email non valido. Il carattere jolly (*) deve essere l'intera parte locale.",
|
||||
"otpEmailSmtpRequired": "SMTP Richiesto",
|
||||
"otpEmailSmtpRequiredDescription": "SMTP deve essere abilitato sul server per utilizzare l'autenticazione con password monouso.",
|
||||
"otpEmailTitle": "Password Monouso",
|
||||
"otpEmailTitleDescription": "Richiedi autenticazione basata su email per l'accesso alle risorse",
|
||||
"otpEmailWhitelist": "Lista Autorizzazioni Email",
|
||||
"otpEmailWhitelistList": "Email Autorizzate",
|
||||
"otpEmailWhitelistListDescription": "Solo gli utenti con questi indirizzi email potranno accedere a questa risorsa. Verrà richiesto loro di inserire una password monouso inviata alla loro email. I caratteri jolly (*@example.com) possono essere utilizzati per consentire qualsiasi indirizzo email da un dominio.",
|
||||
"otpEmailWhitelistSave": "Salva Lista Autorizzazioni",
|
||||
"passwordAdd": "Aggiungi Password",
|
||||
"passwordRemove": "Rimuovi Password",
|
||||
"pincodeAdd": "Aggiungi Codice PIN",
|
||||
"pincodeRemove": "Rimuovi Codice PIN",
|
||||
"resourceAuthMethods": "Metodi di Autenticazione",
|
||||
"resourceAuthMethodsDescriptions": "Consenti l'accesso alla risorsa tramite metodi di autenticazione aggiuntivi",
|
||||
"resourceAuthSettingsSave": "Salvato con successo",
|
||||
"resourceAuthSettingsSaveDescription": "Le impostazioni di autenticazione sono state salvate",
|
||||
"resourceErrorAuthFetch": "Impossibile recuperare i dati",
|
||||
"resourceErrorAuthFetchDescription": "Si è verificato un errore durante il recupero dei dati",
|
||||
"resourceErrorPasswordRemove": "Errore nella rimozione della password della risorsa",
|
||||
"resourceErrorPasswordRemoveDescription": "Si è verificato un errore durante la rimozione della password della risorsa",
|
||||
"resourceErrorPasswordSetup": "Errore nell'impostazione della password della risorsa",
|
||||
"resourceErrorPasswordSetupDescription": "Si è verificato un errore durante l'impostazione della password della risorsa",
|
||||
"resourceErrorPincodeRemove": "Errore nella rimozione del codice PIN della risorsa",
|
||||
"resourceErrorPincodeRemoveDescription": "Si è verificato un errore durante la rimozione del codice PIN della risorsa",
|
||||
"resourceErrorPincodeSetup": "Errore nell'impostazione del codice PIN della risorsa",
|
||||
"resourceErrorPincodeSetupDescription": "Si è verificato un errore durante l'impostazione del codice PIN della risorsa",
|
||||
"resourceErrorUsersRolesSave": "Impossibile impostare i ruoli",
|
||||
"resourceErrorUsersRolesSaveDescription": "Si è verificato un errore durante l'impostazione dei ruoli",
|
||||
"resourceErrorWhitelistSave": "Impossibile salvare la lista autorizzazioni",
|
||||
"resourceErrorWhitelistSaveDescription": "Si è verificato un errore durante il salvataggio della lista autorizzazioni",
|
||||
"resourcePasswordSubmit": "Abilita Protezione Password",
|
||||
"resourcePasswordRemove": "Password della risorsa rimossa",
|
||||
"resourcePasswordRemoveDescription": "La password della risorsa è stata rimossa con successo",
|
||||
"resourcePasswordSetup": "Password della risorsa impostata",
|
||||
"resourcePasswordSetupDescription": "La password della risorsa è stata impostata con successo",
|
||||
"resourcePasswordSetupTitle": "Imposta Password",
|
||||
"resourcePasswordSetupTitleDescription": "Imposta una password per proteggere questa risorsa",
|
||||
"resourcePincode": "Codice PIN",
|
||||
"resourcePincodeSubmit": "Abilita Protezione Codice PIN",
|
||||
"resourcePincodeProtection": "Protezione Codice PIN {status}",
|
||||
"resourcePincodeRemove": "Codice PIN della risorsa rimosso",
|
||||
"resourcePincodeRemoveDescription": "Il codice PIN della risorsa è stato rimosso con successo",
|
||||
"resourcePincodeSetup": "Codice PIN della risorsa impostato",
|
||||
"resourcePincodeSetupDescription": "Il codice PIN della risorsa è stato impostato con successo",
|
||||
"resourcePincodeSetupTitle": "Imposta Codice PIN",
|
||||
"resourcePincodeSetupTitleDescription": "Imposta un codice PIN per proteggere questa risorsa",
|
||||
"resourceRoleDescription": "Gli amministratori possono sempre accedere a questa risorsa.",
|
||||
"resourceUsersRoles": "Utenti e Ruoli",
|
||||
"resourceUsersRolesDescription": "Configura quali utenti e ruoli possono visitare questa risorsa",
|
||||
"resourceUsersRolesSubmit": "Salva Utenti e Ruoli",
|
||||
"resourceWhitelistSave": "Salvato con successo",
|
||||
"resourceWhitelistSaveDescription": "Le impostazioni della lista autorizzazioni sono state salvate",
|
||||
"ssoUse": "Usa SSO della Piattaforma",
|
||||
"ssoUseDescription": "Gli utenti esistenti dovranno accedere solo una volta per tutte le risorse che hanno questa opzione abilitata.",
|
||||
"proxyErrorInvalidPort": "Numero porta non valido",
|
||||
"subdomainErrorInvalid": "Sottodominio non valido",
|
||||
"domainErrorFetch": "Errore nel recupero dei domini",
|
||||
"domainErrorFetchDescription": "Si è verificato un errore durante il recupero dei domini",
|
||||
"resourceErrorUpdate": "Impossibile aggiornare la risorsa",
|
||||
"resourceErrorUpdateDescription": "Si è verificato un errore durante l'aggiornamento della risorsa",
|
||||
"resourceUpdated": "Risorsa aggiornata",
|
||||
"resourceUpdatedDescription": "La risorsa è stata aggiornata con successo",
|
||||
"resourceErrorTransfer": "Impossibile trasferire la risorsa",
|
||||
"resourceErrorTransferDescription": "Si è verificato un errore durante il trasferimento della risorsa",
|
||||
"resourceTransferred": "Risorsa trasferita",
|
||||
"resourceTransferredDescription": "La risorsa è stata trasferita con successo",
|
||||
"resourceErrorToggle": "Impossibile alternare la risorsa",
|
||||
"resourceErrorToggleDescription": "Si è verificato un errore durante l'aggiornamento della risorsa",
|
||||
"resourceVisibilityTitle": "Visibilità",
|
||||
"resourceVisibilityTitleDescription": "Abilita o disabilita completamente la visibilità della risorsa",
|
||||
"resourceGeneral": "Impostazioni Generali",
|
||||
"resourceGeneralDescription": "Configura le impostazioni generali per questa risorsa",
|
||||
"resourceEnable": "Abilita Risorsa",
|
||||
"resourceTransfer": "Trasferisci Risorsa",
|
||||
"resourceTransferDescription": "Trasferisci questa risorsa a un sito diverso",
|
||||
"resourceTransferSubmit": "Trasferisci Risorsa",
|
||||
"siteDestination": "Sito Di Destinazione",
|
||||
"searchSites": "Cerca siti",
|
||||
"accessRoleCreate": "Crea Ruolo",
|
||||
"accessRoleCreateDescription": "Crea un nuovo ruolo per raggruppare gli utenti e gestire i loro permessi.",
|
||||
"accessRoleCreateSubmit": "Crea Ruolo",
|
||||
"accessRoleCreated": "Ruolo creato",
|
||||
"accessRoleCreatedDescription": "Il ruolo è stato creato con successo.",
|
||||
"accessRoleErrorCreate": "Impossibile creare il ruolo",
|
||||
"accessRoleErrorCreateDescription": "Si è verificato un errore durante la creazione del ruolo.",
|
||||
"accessRoleErrorNewRequired": "Nuovo ruolo richiesto",
|
||||
"accessRoleErrorRemove": "Impossibile rimuovere il ruolo",
|
||||
"accessRoleErrorRemoveDescription": "Si è verificato un errore durante la rimozione del ruolo.",
|
||||
"accessRoleName": "Nome Del Ruolo",
|
||||
"accessRoleQuestionRemove": "Stai per eliminare il ruolo <b>{name}</b>. Non puoi annullare questa azione.",
|
||||
"accessRoleRemove": "Rimuovi Ruolo",
|
||||
"accessRoleRemoveDescription": "Rimuovi un ruolo dall'organizzazione",
|
||||
"accessRoleRemoveSubmit": "Rimuovi Ruolo",
|
||||
"accessRoleRemoved": "Ruolo rimosso",
|
||||
"accessRoleRemovedDescription": "Il ruolo è stato rimosso con successo.",
|
||||
"accessRoleRequiredRemove": "Prima di eliminare questo ruolo, seleziona un nuovo ruolo a cui trasferire i membri esistenti.",
|
||||
"manage": "Gestisci",
|
||||
"sitesNotFound": "Nessun sito trovato."
|
||||
}
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
"siteCreateDescription2": "Wykonaj poniższe kroki, aby utworzyć i połączyć nową witrynę",
|
||||
"siteCreateDescription": "Utwórz nową witrynę, aby rozpocząć łączenie zasobów",
|
||||
"close": "Zamknij",
|
||||
"siteNameMin": "Nazwa musi mieć co najmniej 2 znaki.",
|
||||
"siteNameMax": "Nazwa nie może przekraczać 30 znaków.",
|
||||
"siteErrorCreate": "Błąd podczas tworzenia witryny",
|
||||
"siteErrorCreateKeyPair": "Nie znaleziono pary kluczy lub domyślnych ustawień witryny",
|
||||
"siteErrorCreateDefaults": "Nie znaleziono domyślnych ustawień witryny",
|
||||
|
@ -71,7 +69,7 @@
|
|||
"dockerRun": "Uruchom Docker",
|
||||
"siteLearnLocal": "Lokalne witryny nie tunelowają, dowiedz się więcej",
|
||||
"siteConfirmCopy": "Skopiowałem konfigurację",
|
||||
"searchSites": "Szukaj witryn...",
|
||||
"searchSitesProgress": "Szukaj witryn...",
|
||||
"siteAdd": "Dodaj witrynę",
|
||||
"siteInstallNewt": "Zainstaluj Newt",
|
||||
"siteInstallNewtDescription": "Uruchom Newt w swoim systemie",
|
||||
|
@ -111,7 +109,7 @@
|
|||
"shareErrorDelete": "Nie udało się usunąć linku",
|
||||
"shareErrorDeleteMessage": "Wystąpił błąd podczas usuwania linku",
|
||||
"shareDeleted": "Link usunięty",
|
||||
"shareDeletedDesciption": "Link został usunięty",
|
||||
"shareDeletedDescription": "Link został usunięty",
|
||||
"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",
|
||||
"usageExamples": "Przykłady użycia",
|
||||
|
@ -234,7 +232,7 @@
|
|||
"username": "Nazwa użytkownika",
|
||||
"identityProvider": "Dostawca tożsamości",
|
||||
"role": "Rola",
|
||||
"accessRoleNameRequired": "Nazwa jest wymagana",
|
||||
"nameRequired": "Nazwa jest wymagana",
|
||||
"accessRolesManage": "Zarządzaj rolami",
|
||||
"accessRolesDescription": "Skonfiguruj role do zarządzania dostępem do Twojej organizacji",
|
||||
"accessRolesSearch": "Szukaj ról...",
|
||||
|
@ -252,8 +250,6 @@
|
|||
"years": "Lata",
|
||||
"day": "{count, plural, =1 {# dzień} other {# dni}}",
|
||||
"apiKeysTitle": "Informacje o kluczu API",
|
||||
"apiKeysNameMin": "Nazwa musi mieć co najmniej 2 znaki.",
|
||||
"apiKeysNameMax": "Nazwa nie może być dłuższa niż 255 znaków.",
|
||||
"apiKeysConfirmCopy2": "Musisz potwierdzić, że skopiowałeś klucz API.",
|
||||
"apiKeysErrorCreate": "Błąd podczas tworzenia klucza API",
|
||||
"apiKeysErrorSetPermission": "Błąd podczas ustawiania uprawnień",
|
||||
|
@ -382,5 +378,319 @@
|
|||
"inviteValidityPeriodSelect": "Wybierz okres ważności",
|
||||
"inviteRegenerateMessage": "Zaproszenie zostało ponownie wygenerowane. Użytkownik musi uzyskać dostęp do poniższego linku, aby zaakceptować zaproszenie.",
|
||||
"inviteRegenerateButton": "Wygeneruj ponownie",
|
||||
"expiresAt": "Wygasa w dniu"
|
||||
"expiresAt": "Wygasa w dniu",
|
||||
"accessRoleUnknown": "Nieznana rola",
|
||||
"placeholder": "Symbol zastępczy",
|
||||
"userErrorOrgRemove": "Nie udało się usunąć użytkownika",
|
||||
"userErrorOrgRemoveDescription": "Wystąpił błąd podczas usuwania użytkownika.",
|
||||
"userOrgRemoved": "Użytkownik usunięty",
|
||||
"userOrgRemovedDescription": "Użytkownik {email} został usunięty z organizacji.",
|
||||
"userQuestionOrgRemove": "Czy na pewno chcesz usunąć <b>{email}</b> z organizacji?",
|
||||
"userMessageOrgRemove": "Po usunięciu ten użytkownik nie będzie miał już dostępu do organizacji. Zawsze możesz ponownie go zaprosić później, ale będzie musiał ponownie zaakceptować zaproszenie.",
|
||||
"userMessageOrgConfirm": "Aby potwierdzić, wpisz nazwę użytkownika poniżej.",
|
||||
"userRemoveOrgConfirm": "Potwierdź usunięcie użytkownika",
|
||||
"userRemoveOrg": "Usuń użytkownika z organizacji",
|
||||
"users": "Użytkownicy",
|
||||
"accessRoleMember": "Członek",
|
||||
"accessRoleOwner": "Właściciel",
|
||||
"userConfirmed": "Potwierdzony",
|
||||
"idpNameInternal": "Wewnętrzny",
|
||||
"emailInvalid": "Nieprawidłowy adres email",
|
||||
"inviteValidityDuration": "Proszę wybrać okres ważności",
|
||||
"accessRoleSelectPlease": "Proszę wybrać rolę",
|
||||
"usernameRequired": "Nazwa użytkownika jest wymagana",
|
||||
"idpSelectPlease": "Proszę wybrać dostawcę tożsamości",
|
||||
"idpGenericOidc": "Ogólny dostawca OAuth2/OIDC.",
|
||||
"accessRoleErrorFetch": "Nie udało się pobrać ról",
|
||||
"accessRoleErrorFetchDescription": "Wystąpił błąd podczas pobierania ról",
|
||||
"idpErrorFetch": "Nie udało się pobrać dostawców tożsamości",
|
||||
"idpErrorFetchDescription": "Wystąpił błąd podczas pobierania dostawców tożsamości",
|
||||
"userErrorExists": "Użytkownik już istnieje",
|
||||
"userErrorExistsDescription": "Ten użytkownik jest już członkiem organizacji.",
|
||||
"inviteError": "Nie udało się zaprosić użytkownika",
|
||||
"inviteErrorDescription": "Wystąpił błąd podczas zapraszania użytkownika",
|
||||
"userInvited": "Użytkownik zaproszony",
|
||||
"userInvitedDescription": "Użytkownik został pomyślnie zaproszony.",
|
||||
"userErrorCreate": "Nie udało się utworzyć użytkownika",
|
||||
"userErrorCreateDescription": "Wystąpił błąd podczas tworzenia użytkownika",
|
||||
"userCreated": "Utworzono użytkownika",
|
||||
"userCreatedDescription": "Użytkownik został pomyślnie utworzony.",
|
||||
"userTypeInternal": "Użytkownik wewnętrzny",
|
||||
"userTypeInternalDescription": "Zaproś użytkownika do bezpośredniego dołączenia do Twojej organizacji.",
|
||||
"userTypeExternal": "Użytkownik zewnętrzny",
|
||||
"userTypeExternalDescription": "Utwórz użytkownika z zewnętrznym dostawcą tożsamości.",
|
||||
"accessUserCreateDescription": "Wykonaj poniższe kroki, aby utworzyć nowego użytkownika",
|
||||
"userSeeAll": "Zobacz wszystkich użytkowników",
|
||||
"userTypeTitle": "Typ użytkownika",
|
||||
"userTypeDescription": "Określ, jak chcesz utworzyć użytkownika",
|
||||
"userSettings": "Informacje o użytkowniku",
|
||||
"userSettingsDescription": "Wprowadź dane nowego użytkownika",
|
||||
"inviteEmailSent": "Wyślij email z zaproszeniem do użytkownika",
|
||||
"inviteValid": "Ważne przez",
|
||||
"selectDuration": "Wybierz okres",
|
||||
"accessRoleSelect": "Wybierz rolę",
|
||||
"inviteEmailSentDescription": "Email został wysłany do użytkownika z linkiem dostępu poniżej. Musi on uzyskać dostęp do linku, aby zaakceptować zaproszenie.",
|
||||
"inviteSentDescription": "Użytkownik został zaproszony. Musi uzyskać dostęp do poniższego linku, aby zaakceptować zaproszenie.",
|
||||
"inviteExpiresIn": "Zaproszenie wygaśnie za <b>{days, plural, =1 {# dzień} other {# dni}}</b>.",
|
||||
"idpTitle": "Dostawca tożsamości",
|
||||
"idpSelect": "Wybierz dostawcę tożsamości dla użytkownika zewnętrznego",
|
||||
"idpNotConfigured": "Nie skonfigurowano żadnych dostawców tożsamości. Skonfiguruj dostawcę tożsamości przed utworzeniem użytkowników zewnętrznych.",
|
||||
"usernameUniq": "Musi to odpowiadać unikalnej nazwie użytkownika istniejącej u wybranego dostawcy tożsamości.",
|
||||
"emailOptional": "Email (Opcjonalnie)",
|
||||
"nameOptional": "Nazwa (Opcjonalnie)",
|
||||
"accessControls": "Kontrola dostępu",
|
||||
"userDescription2": "Zarządzaj ustawieniami tego użytkownika",
|
||||
"accessRoleErrorAdd": "Nie udało się dodać użytkownika do roli",
|
||||
"accessRoleErrorAddDescription": "Wystąpił błąd podczas dodawania użytkownika do roli.",
|
||||
"userSaved": "Użytkownik zapisany",
|
||||
"userSavedDescription": "Użytkownik został zaktualizowany.",
|
||||
"accessControlsDescription": "Zarządzaj tym, do czego użytkownik ma dostęp i co może robić w organizacji",
|
||||
"accessControlsSubmit": "Zapisz kontrole dostępu",
|
||||
"roles": "Role",
|
||||
"accessUsersRoles": "Zarządzaj użytkownikami i rolami",
|
||||
"accessUsersRolesDescription": "Zapraszaj użytkowników i dodawaj ich do ról, aby zarządzać dostępem do Twojej organizacji",
|
||||
"key": "Klucz",
|
||||
"createdAt": "Utworzono",
|
||||
"proxyErrorInvalidHeader": "Nieprawidłowa wartość niestandardowego nagłówka hosta. Użyj formatu nazwy domeny lub zapisz pusty, aby usunąć niestandardowy nagłówek hosta.",
|
||||
"proxyErrorTls": "Nieprawidłowa nazwa serwera TLS. Użyj formatu nazwy domeny lub zapisz pusty, aby usunąć nazwę serwera TLS.",
|
||||
"targetErrorFetch": "Nie udało się pobrać celów",
|
||||
"targetErrorFetchDescription": "Wystąpił błąd podczas pobierania celów",
|
||||
"siteErrorFetch": "Nie udało się pobrać zasobu",
|
||||
"siteErrorFetchDescription": "Wystąpił błąd podczas pobierania zasobu",
|
||||
"targetErrorDuplicate": "Duplikat celu",
|
||||
"targetErrorDuplicateDescription": "Cel o tych ustawieniach już istnieje",
|
||||
"targetWireGuardErrorInvalidIp": "Nieprawidłowy adres IP celu",
|
||||
"targetWireGuardErrorInvalidIpDescription": "Adres IP celu musi znajdować się w podsieci witryny",
|
||||
"targetsUpdated": "Cele zaktualizowane",
|
||||
"targetsUpdatedDescription": "Cele i ustawienia zostały pomyślnie zaktualizowane",
|
||||
"targetsErrorUpdate": "Nie udało się zaktualizować celów",
|
||||
"targetsErrorUpdateDescription": "Wystąpił błąd podczas aktualizacji celów",
|
||||
"targetTlsUpdate": "Ustawienia TLS zaktualizowane",
|
||||
"targetTlsUpdateDescription": "Twoje ustawienia TLS zostały pomyślnie zaktualizowane",
|
||||
"targetErrorTlsUpdate": "Nie udało się zaktualizować ustawień TLS",
|
||||
"targetErrorTlsUpdateDescription": "Wystąpił błąd podczas aktualizacji ustawień TLS",
|
||||
"proxyUpdated": "Ustawienia proxy zaktualizowane",
|
||||
"proxyUpdatedDescription": "Twoje ustawienia proxy zostały pomyślnie zaktualizowane",
|
||||
"proxyErrorUpdate": "Nie udało się zaktualizować ustawień proxy",
|
||||
"proxyErrorUpdateDescription": "Wystąpił błąd podczas aktualizacji ustawień proxy",
|
||||
"targetAddr": "IP / Nazwa hosta",
|
||||
"targetPort": "Port",
|
||||
"targetProtocol": "Protokół",
|
||||
"targetTlsSettings": "Ustawienia HTTPS & TLS",
|
||||
"targetTlsSettingsDescription": "Skonfiguruj ustawienia TLS dla swojego zasobu",
|
||||
"targetTlsSettingsAdvanced": "Zaawansowane ustawienia TLS",
|
||||
"targetTlsSni": "Nazwa serwera TLS (SNI)",
|
||||
"targetTlsSniDescription": "Nazwa serwera TLS do użycia dla SNI. Pozostaw puste, aby użyć domyślnej.",
|
||||
"targetTlsSubmit": "Zapisz ustawienia",
|
||||
"targets": "Konfiguracja celów",
|
||||
"targetsDescription": "Skonfiguruj cele do kierowania ruchu do swoich usług",
|
||||
"targetStickySessions": "Włącz sesje trwałe",
|
||||
"targetStickySessionsDescription": "Utrzymuj połączenia na tym samym celu backendowym przez całą sesję.",
|
||||
"methodSelect": "Wybierz metodę",
|
||||
"targetSubmit": "Dodaj cel",
|
||||
"targetNoOne": "Brak celów. Dodaj cel używając formularza.",
|
||||
"targetNoOneDescription": "Dodanie więcej niż jednego celu powyżej włączy równoważenie obciążenia.",
|
||||
"targetsSubmit": "Zapisz cele",
|
||||
"proxyAdditional": "Dodatkowe ustawienia proxy",
|
||||
"proxyAdditionalDescription": "Skonfiguruj jak twój zasób obsługuje ustawienia proxy",
|
||||
"proxyCustomHeader": "Niestandardowy nagłówek hosta",
|
||||
"proxyCustomHeaderDescription": "Nagłówek hosta do ustawienia podczas proxy żądań. Pozostaw puste, aby użyć domyślnego.",
|
||||
"proxyAdditionalSubmit": "Zapisz ustawienia proxy",
|
||||
"subnetMaskErrorInvalid": "Nieprawidłowa maska podsieci. Musi być między 0 a 32.",
|
||||
"ipAddressErrorInvalidFormat": "Nieprawidłowy format adresu IP",
|
||||
"ipAddressErrorInvalidOctet": "Nieprawidłowy oktet adresu IP",
|
||||
"path": "Ścieżka",
|
||||
"ipAddressRange": "Zakres IP",
|
||||
"rulesErrorFetch": "Nie udało się pobrać reguł",
|
||||
"rulesErrorFetchDescription": "Wystąpił błąd podczas pobierania reguł",
|
||||
"rulesErrorDuplicate": "Duplikat reguły",
|
||||
"rulesErrorDuplicateDescription": "Reguła o tych ustawieniach już istnieje",
|
||||
"rulesErrorInvalidIpAddressRange": "Nieprawidłowy CIDR",
|
||||
"rulesErrorInvalidIpAddressRangeDescription": "Wprowadź prawidłową wartość CIDR",
|
||||
"rulesErrorInvalidUrl": "Nieprawidłowa ścieżka URL",
|
||||
"rulesErrorInvalidUrlDescription": "Wprowadź prawidłową wartość ścieżki URL",
|
||||
"rulesErrorInvalidIpAddress": "Nieprawidłowe IP",
|
||||
"rulesErrorInvalidIpAddressDescription": "Wprowadź prawidłowy adres IP",
|
||||
"rulesErrorUpdate": "Nie udało się zaktualizować reguł",
|
||||
"rulesErrorUpdateDescription": "Wystąpił błąd podczas aktualizacji reguł",
|
||||
"rulesUpdated": "Włącz reguły",
|
||||
"rulesUpdatedDescription": "Ocena reguł została zaktualizowana",
|
||||
"rulesMatchIpAddressRangeDescription": "Wprowadź adres w formacie CIDR (np. 103.21.244.0/22)",
|
||||
"rulesMatchIpAddress": "Wprowadź adres IP (np. 103.21.244.12)",
|
||||
"rulesMatchUrl": "Wprowadź ścieżkę URL lub wzorzec (np. /api/v1/todos lub /api/v1/*)",
|
||||
"rulesErrorInvalidPriority": "Nieprawidłowy priorytet",
|
||||
"rulesErrorInvalidPriorityDescription": "Wprowadź prawidłowy priorytet",
|
||||
"rulesErrorDuplicatePriority": "Zduplikowane priorytety",
|
||||
"rulesErrorDuplicatePriorityDescription": "Wprowadź unikalne priorytety",
|
||||
"ruleUpdated": "Reguły zaktualizowane",
|
||||
"ruleUpdatedDescription": "Reguły zostały pomyślnie zaktualizowane",
|
||||
"ruleErrorUpdate": "Operacja nie powiodła się",
|
||||
"ruleErrorUpdateDescription": "Wystąpił błąd podczas operacji zapisu",
|
||||
"rulesPriority": "Priorytet",
|
||||
"rulesAction": "Akcja",
|
||||
"rulesMatchType": "Typ dopasowania",
|
||||
"value": "Wartość",
|
||||
"rulesAbout": "O regułach",
|
||||
"rulesAboutDescription": "Reguły pozwalają kontrolować dostęp do zasobu na podstawie zestawu kryteriów. Możesz tworzyć reguły zezwalające lub odmawiające dostępu na podstawie adresu IP lub ścieżki URL.",
|
||||
"rulesActions": "Akcje",
|
||||
"rulesActionAlwaysAllow": "Zawsze zezwalaj: Pomiń wszystkie metody uwierzytelniania",
|
||||
"rulesActionAlwaysDeny": "Zawsze odmawiaj: Blokuj wszystkie żądania; nie można próbować uwierzytelniania",
|
||||
"rulesMatchCriteria": "Kryteria dopasowania",
|
||||
"rulesMatchCriteriaIpAddress": "Dopasuj konkretny adres IP",
|
||||
"rulesMatchCriteriaIpAddressRange": "Dopasuj zakres adresów IP w notacji CIDR",
|
||||
"rulesMatchCriteriaUrl": "Dopasuj ścieżkę URL lub wzorzec",
|
||||
"rulesEnable": "Włącz reguły",
|
||||
"rulesEnableDescription": "Włącz lub wyłącz ocenę reguł dla tego zasobu",
|
||||
"rulesResource": "Konfiguracja reguł zasobu",
|
||||
"rulesResourceDescription": "Skonfiguruj reguły kontroli dostępu do zasobu",
|
||||
"ruleSubmit": "Dodaj regułę",
|
||||
"rulesNoOne": "Brak reguł. Dodaj regułę używając formularza.",
|
||||
"rulesOrder": "Reguły są oceniane według priorytetu w kolejności rosnącej.",
|
||||
"rulesSubmit": "Zapisz reguły",
|
||||
"resourceErrorCreate": "Błąd podczas tworzenia zasobu",
|
||||
"resourceErrorCreateDescription": "Wystąpił błąd podczas tworzenia zasobu",
|
||||
"resourceErrorCreateMessage": "Błąd podczas tworzenia zasobu:",
|
||||
"resourceErrorCreateMessageDescription": "Wystąpił nieoczekiwany błąd",
|
||||
"sitesErrorFetch": "Błąd podczas pobierania witryn",
|
||||
"sitesErrorFetchDescription": "Wystąpił błąd podczas pobierania witryn",
|
||||
"domainsErrorFetch": "Błąd podczas pobierania domen",
|
||||
"domainsErrorFetchDescription": "Wystąpił błąd podczas pobierania domen",
|
||||
"none": "Brak",
|
||||
"unknown": "Nieznany",
|
||||
"resources": "Zasoby",
|
||||
"resourcesDescription": "Zasoby są proxy do aplikacji działających w Twojej sieci prywatnej. Utwórz zasób dla dowolnej usługi HTTP/HTTPS lub surowej TCP/UDP w Twojej sieci prywatnej. Każdy zasób musi być połączony z witryną, aby umożliwić prywatne, bezpieczne połączenie przez zaszyfrowany tunel WireGuard.",
|
||||
"resourcesWireGuardConnect": "Bezpieczne połączenie z szyfrowaniem WireGuard",
|
||||
"resourcesMultipleAuthenticationMethods": "Skonfiguruj wiele metod uwierzytelniania",
|
||||
"resourcesUsersRolesAccess": "Kontrola dostępu oparta na użytkownikach i rolach",
|
||||
"resourcesErrorUpdate": "Nie udało się przełączyć zasobu",
|
||||
"resourcesErrorUpdateDescription": "Wystąpił błąd podczas aktualizacji zasobu",
|
||||
"access": "Dostęp",
|
||||
"shareLink": "Link udostępniania {resource}",
|
||||
"resourceSelect": "Wybierz zasób",
|
||||
"shareLinks": "Linki udostępniania",
|
||||
"share": "Linki do udostępnienia",
|
||||
"shareDescription2": "Twórz linki do udostępniania swoich zasobów. Linki zapewniają tymczasowy lub nieograniczony dostęp do zasobu. Podczas tworzenia linku możesz skonfigurować okres jego ważności.",
|
||||
"shareEasyCreate": "Łatwe tworzenie i udostępnianie",
|
||||
"shareConfigurableExpirationDuration": "Konfigurowalny okres ważności",
|
||||
"shareSecureAndRevocable": "Bezpieczne i odwoływalne",
|
||||
"nameMin": "Nazwa musi mieć co najmniej {len} znaków.",
|
||||
"nameMax": "Nazwa nie może być dłuższa niż {len} znaków.",
|
||||
"sitesConfirmCopy": "Potwierdź, że skopiowałeś konfigurację.",
|
||||
"unknownCommand": "Nieznane polecenie",
|
||||
"newtErrorFetchReleases": "Nie udało się pobrać informacji o wydaniu: {err}",
|
||||
"newtErrorFetchLatest": "Błąd podczas pobierania najnowszego wydania: {err}",
|
||||
"newtEndpoint": "Punkt końcowy Newt",
|
||||
"newtId": "ID Newt",
|
||||
"newtSecretKey": "Klucz tajny Newt",
|
||||
"architecture": "Architektura",
|
||||
"sites": "Witryny",
|
||||
"siteWgAnyClients": "Użyj dowolnego klienta WireGuard do połączenia. Będziesz musiał adresować swoje zasoby wewnętrzne używając IP peera.",
|
||||
"siteWgCompatibleAllClients": "Kompatybilny ze wszystkimi klientami WireGuard",
|
||||
"siteWgManualConfigurationRequired": "Wymagana konfiguracja ręczna",
|
||||
"userErrorNotAdminOrOwner": "Użytkownik nie jest administratorem ani właścicielem",
|
||||
"pangolinSettings": "Ustawienia - Pangolin",
|
||||
"accessRoleYour": "Twoja rola:",
|
||||
"accessRoleSelect2": "Wybierz rolę",
|
||||
"accessUserSelect": "Wybierz użytkownika",
|
||||
"otpEmailEnter": "Wprowadź adres e-mail",
|
||||
"otpEmailEnterDescription": "Naciśnij enter, aby dodać adres e-mail po wpisaniu go w polu.",
|
||||
"otpEmailErrorInvalid": "Nieprawidłowy adres e-mail. Znak wieloznaczny (*) musi być całą częścią lokalną.",
|
||||
"otpEmailSmtpRequired": "Wymagany SMTP",
|
||||
"otpEmailSmtpRequiredDescription": "SMTP musi być włączony na serwerze, aby korzystać z uwierzytelniania jednorazowym hasłem.",
|
||||
"otpEmailTitle": "Hasła jednorazowe",
|
||||
"otpEmailTitleDescription": "Wymagaj uwierzytelniania opartego na e-mail dla dostępu do zasobu",
|
||||
"otpEmailWhitelist": "Biała lista e-mail",
|
||||
"otpEmailWhitelistList": "Dozwolone adresy e-mail",
|
||||
"otpEmailWhitelistListDescription": "Tylko użytkownicy z tymi adresami e-mail będą mieli dostęp do tego zasobu. Otrzymają prośbę o wprowadzenie jednorazowego hasła wysłanego na ich e-mail. Można użyć znaków wieloznacznych (*@example.com), aby zezwolić na dowolny adres e-mail z domeny.",
|
||||
"otpEmailWhitelistSave": "Zapisz białą listę",
|
||||
"passwordAdd": "Dodaj hasło",
|
||||
"passwordRemove": "Usuń hasło",
|
||||
"pincodeAdd": "Dodaj kod PIN",
|
||||
"pincodeRemove": "Usuń kod PIN",
|
||||
"resourceAuthMethods": "Metody uwierzytelniania",
|
||||
"resourceAuthMethodsDescriptions": "Zezwól na dostęp do zasobu przez dodatkowe metody uwierzytelniania",
|
||||
"resourceAuthSettingsSave": "Zapisano pomyślnie",
|
||||
"resourceAuthSettingsSaveDescription": "Ustawienia uwierzytelniania zostały zapisane",
|
||||
"resourceErrorAuthFetch": "Nie udało się pobrać danych",
|
||||
"resourceErrorAuthFetchDescription": "Wystąpił błąd podczas pobierania danych",
|
||||
"resourceErrorPasswordRemove": "Błąd podczas usuwania hasła zasobu",
|
||||
"resourceErrorPasswordRemoveDescription": "Wystąpił błąd podczas usuwania hasła zasobu",
|
||||
"resourceErrorPasswordSetup": "Błąd podczas ustawiania hasła zasobu",
|
||||
"resourceErrorPasswordSetupDescription": "Wystąpił błąd podczas ustawiania hasła zasobu",
|
||||
"resourceErrorPincodeRemove": "Błąd podczas usuwania kodu PIN zasobu",
|
||||
"resourceErrorPincodeRemoveDescription": "Wystąpił błąd podczas usuwania kodu PIN zasobu",
|
||||
"resourceErrorPincodeSetup": "Błąd podczas ustawiania kodu PIN zasobu",
|
||||
"resourceErrorPincodeSetupDescription": "Wystąpił błąd podczas ustawiania kodu PIN zasobu",
|
||||
"resourceErrorUsersRolesSave": "Nie udało się ustawić ról",
|
||||
"resourceErrorUsersRolesSaveDescription": "Wystąpił błąd podczas ustawiania ról",
|
||||
"resourceErrorWhitelistSave": "Nie udało się zapisać białej listy",
|
||||
"resourceErrorWhitelistSaveDescription": "Wystąpił błąd podczas zapisywania białej listy",
|
||||
"resourcePasswordSubmit": "Włącz ochronę hasłem",
|
||||
"resourcePasswordRemove": "Hasło zasobu zostało usunięte",
|
||||
"resourcePasswordRemoveDescription": "Hasło zasobu zostało pomyślnie usunięte",
|
||||
"resourcePasswordSetup": "Ustawiono hasło zasobu",
|
||||
"resourcePasswordSetupDescription": "Hasło zasobu zostało pomyślnie ustawione",
|
||||
"resourcePasswordSetupTitle": "Ustaw hasło",
|
||||
"resourcePasswordSetupTitleDescription": "Ustaw hasło, aby chronić ten zasób",
|
||||
"resourcePincode": "Kod PIN",
|
||||
"resourcePincodeSubmit": "Włącz ochronę kodem PIN",
|
||||
"resourcePincodeProtection": "Ochrona kodem PIN {status}",
|
||||
"resourcePincodeRemove": "Usunięto kod PIN zasobu",
|
||||
"resourcePincodeRemoveDescription": "Kod PIN zasobu został pomyślnie usunięty",
|
||||
"resourcePincodeSetup": "Ustawiono kod PIN zasobu",
|
||||
"resourcePincodeSetupDescription": "Kod PIN zasobu został pomyślnie ustawiony",
|
||||
"resourcePincodeSetupTitle": "Ustaw kod PIN",
|
||||
"resourcePincodeSetupTitleDescription": "Ustaw kod PIN, aby chronić ten zasób",
|
||||
"resourceRoleDescription": "Administratorzy zawsze mają dostęp do tego zasobu.",
|
||||
"resourceUsersRoles": "Użytkownicy i role",
|
||||
"resourceUsersRolesDescription": "Skonfiguruj, którzy użytkownicy i role mogą odwiedzać ten zasób",
|
||||
"resourceUsersRolesSubmit": "Zapisz użytkowników i role",
|
||||
"resourceWhitelistSave": "Zapisano pomyślnie",
|
||||
"resourceWhitelistSaveDescription": "Ustawienia białej listy zostały zapisane",
|
||||
"ssoUse": "Użyj platformy SSO",
|
||||
"ssoUseDescription": "Istniejący użytkownicy będą musieli zalogować się tylko raz dla wszystkich zasobów, które mają to włączone.",
|
||||
"proxyErrorInvalidPort": "Nieprawidłowy numer portu",
|
||||
"subdomainErrorInvalid": "Nieprawidłowa poddomena",
|
||||
"domainErrorFetch": "Błąd podczas pobierania domen",
|
||||
"domainErrorFetchDescription": "Wystąpił błąd podczas pobierania domen",
|
||||
"resourceErrorUpdate": "Nie udało się zaktualizować zasobu",
|
||||
"resourceErrorUpdateDescription": "Wystąpił błąd podczas aktualizacji zasobu",
|
||||
"resourceUpdated": "Zasób zaktualizowany",
|
||||
"resourceUpdatedDescription": "Zasób został pomyślnie zaktualizowany",
|
||||
"resourceErrorTransfer": "Nie udało się przenieść zasobu",
|
||||
"resourceErrorTransferDescription": "Wystąpił błąd podczas przenoszenia zasobu",
|
||||
"resourceTransferred": "Zasób przeniesiony",
|
||||
"resourceTransferredDescription": "Zasób został pomyślnie przeniesiony",
|
||||
"resourceErrorToggle": "Nie udało się przełączyć zasobu",
|
||||
"resourceErrorToggleDescription": "Wystąpił błąd podczas aktualizacji zasobu",
|
||||
"resourceVisibilityTitle": "Widoczność",
|
||||
"resourceVisibilityTitleDescription": "Całkowicie włącz lub wyłącz widoczność zasobu",
|
||||
"resourceGeneral": "Ustawienia ogólne",
|
||||
"resourceGeneralDescription": "Skonfiguruj ustawienia ogólne dla tego zasobu",
|
||||
"resourceEnable": "Włącz zasób",
|
||||
"resourceTransfer": "Przenieś zasób",
|
||||
"resourceTransferDescription": "Przenieś ten zasób do innej witryny",
|
||||
"resourceTransferSubmit": "Przenieś zasób",
|
||||
"siteDestination": "Witryna docelowa",
|
||||
"searchSites": "Szukaj witryn",
|
||||
"accessRoleCreate": "Utwórz rolę",
|
||||
"accessRoleCreateDescription": "Utwórz nową rolę aby zgrupować użytkowników i zarządzać ich uprawnieniami.",
|
||||
"accessRoleCreateSubmit": "Utwórz rolę",
|
||||
"accessRoleCreated": "Rola utworzona",
|
||||
"accessRoleCreatedDescription": "Rola została pomyślnie utworzona.",
|
||||
"accessRoleErrorCreate": "Nie udało się utworzyć roli",
|
||||
"accessRoleErrorCreateDescription": "Wystąpił błąd podczas tworzenia roli.",
|
||||
"accessRoleErrorNewRequired": "Nowa rola jest wymagana",
|
||||
"accessRoleErrorRemove": "Nie udało się usunąć roli",
|
||||
"accessRoleErrorRemoveDescription": "Wystąpił błąd podczas usuwania roli.",
|
||||
"accessRoleName": "Nazwa roli",
|
||||
"accessRoleQuestionRemove": "Zamierzasz usunąć rolę <b>{name}</b>. Tej akcji nie można cofnąć.",
|
||||
"accessRoleRemove": "Usuń rolę",
|
||||
"accessRoleRemoveDescription": "Usuń rolę z organizacji",
|
||||
"accessRoleRemoveSubmit": "Usuń rolę",
|
||||
"accessRoleRemoved": "Rola usunięta",
|
||||
"accessRoleRemovedDescription": "Rola została pomyślnie usunięta.",
|
||||
"accessRoleRequiredRemove": "Przed usunięciem tej roli, wybierz nową rolę do której zostaną przeniesieni obecni członkowie.",
|
||||
"manage": "Zarządzaj",
|
||||
"sitesNotFound": "Nie znaleziono witryn."
|
||||
}
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
"siteCreateDescription2": "Siga os passos abaixo para criar e conectar um novo site",
|
||||
"siteCreateDescription": "Crie um novo site para começar a conectar seus recursos",
|
||||
"close": "FECHAR",
|
||||
"siteNameMin": "O nome deve ter pelo menos 2 caracteres.",
|
||||
"siteNameMax": "O nome não deve ter mais de 30 caracteres.",
|
||||
"siteErrorCreate": "Erro ao criar site",
|
||||
"siteErrorCreateKeyPair": "Par de chaves ou padrões do site não encontrados",
|
||||
"siteErrorCreateDefaults": "Padrão do site não encontrado",
|
||||
|
@ -71,7 +69,7 @@
|
|||
"dockerRun": "Execução do Docker",
|
||||
"siteLearnLocal": "Os sites locais não são túneis, saiba mais",
|
||||
"siteConfirmCopy": "Eu copiei a configuração",
|
||||
"searchSites": "Procurar sites...",
|
||||
"searchSitesProgress": "Procurar sites...",
|
||||
"siteAdd": "Adicionar Site",
|
||||
"siteInstallNewt": "Instalar Novo",
|
||||
"siteInstallNewtDescription": "Novo item em execução no seu sistema",
|
||||
|
@ -111,7 +109,7 @@
|
|||
"shareErrorDelete": "Falha ao excluir o link",
|
||||
"shareErrorDeleteMessage": "Ocorreu um erro ao excluir o link",
|
||||
"shareDeleted": "Link excluído",
|
||||
"shareDeletedDesciption": "O link foi eliminado",
|
||||
"shareDeletedDescription": "O link foi eliminado",
|
||||
"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",
|
||||
"usageExamples": "Exemplos de uso",
|
||||
|
@ -234,7 +232,7 @@
|
|||
"username": "Usuário:",
|
||||
"identityProvider": "Provedor de Identidade",
|
||||
"role": "Funções",
|
||||
"accessRoleNameRequired": "O nome é obrigatório",
|
||||
"nameRequired": "O nome é obrigatório",
|
||||
"accessRolesManage": "Gerenciar Funções",
|
||||
"accessRolesDescription": "Configurar funções para gerenciar o acesso à sua organização",
|
||||
"accessRolesSearch": "Pesquisar funções...",
|
||||
|
@ -252,8 +250,6 @@
|
|||
"years": "anos",
|
||||
"day": "{count, plural, =1 {# dia} other {# dias}}",
|
||||
"apiKeysTitle": "Informações da Chave API",
|
||||
"apiKeysNameMin": "O nome deve ter pelo menos 2 caracteres.",
|
||||
"apiKeysNameMax": "O nome não deve ter mais de 255 caracteres.",
|
||||
"apiKeysConfirmCopy2": "Você deve confirmar que copiou a chave API.",
|
||||
"apiKeysErrorCreate": "Erro ao criar chave API",
|
||||
"apiKeysErrorSetPermission": "Erro ao definir permissões",
|
||||
|
@ -382,5 +378,319 @@
|
|||
"inviteValidityPeriodSelect": "Selecione o período de validade",
|
||||
"inviteRegenerateMessage": "O convite foi regenerado. O usuário deve acessar o link abaixo para aceitar o convite.",
|
||||
"inviteRegenerateButton": "Regenerar",
|
||||
"expiresAt": "Expira em"
|
||||
"expiresAt": "Expira em",
|
||||
"accessRoleUnknown": "Função Desconhecida",
|
||||
"placeholder": "Espaço reservado",
|
||||
"userErrorOrgRemove": "Falha ao remover usuário",
|
||||
"userErrorOrgRemoveDescription": "Ocorreu um erro ao remover o usuário.",
|
||||
"userOrgRemoved": "Usuário removido",
|
||||
"userOrgRemovedDescription": "O usuário {email} foi removido da organização.",
|
||||
"userQuestionOrgRemove": "Tem certeza que deseja remover <b>{email}</b> da organização?",
|
||||
"userMessageOrgRemove": "Uma vez removido, este usuário não terá mais acesso à organização. Você sempre pode reconvidá-lo depois, mas eles precisarão aceitar o convite novamente.",
|
||||
"userMessageOrgConfirm": "Para confirmar, digite o nome do usuário abaixo.",
|
||||
"userRemoveOrgConfirm": "Confirmar Remoção do Usuário",
|
||||
"userRemoveOrg": "Remover Usuário da Organização",
|
||||
"users": "Usuários",
|
||||
"accessRoleMember": "Membro",
|
||||
"accessRoleOwner": "Proprietário",
|
||||
"userConfirmed": "Confirmado",
|
||||
"idpNameInternal": "Interno",
|
||||
"emailInvalid": "Endereço de e-mail inválido",
|
||||
"inviteValidityDuration": "Por favor, selecione uma duração",
|
||||
"accessRoleSelectPlease": "Por favor, selecione uma função",
|
||||
"usernameRequired": "Nome de usuário é obrigatório",
|
||||
"idpSelectPlease": "Por favor, selecione um provedor de identidade",
|
||||
"idpGenericOidc": "Provedor genérico OAuth2/OIDC.",
|
||||
"accessRoleErrorFetch": "Falha ao buscar funções",
|
||||
"accessRoleErrorFetchDescription": "Ocorreu um erro ao buscar as funções",
|
||||
"idpErrorFetch": "Falha ao buscar provedores de identidade",
|
||||
"idpErrorFetchDescription": "Ocorreu um erro ao buscar provedores de identidade",
|
||||
"userErrorExists": "Usuário já existe",
|
||||
"userErrorExistsDescription": "Este usuário já é membro da organização.",
|
||||
"inviteError": "Falha ao convidar usuário",
|
||||
"inviteErrorDescription": "Ocorreu um erro ao convidar o usuário",
|
||||
"userInvited": "Usuário convidado",
|
||||
"userInvitedDescription": "O usuário foi convidado com sucesso.",
|
||||
"userErrorCreate": "Falha ao criar usuário",
|
||||
"userErrorCreateDescription": "Ocorreu um erro ao criar o usuário",
|
||||
"userCreated": "Usuário criado",
|
||||
"userCreatedDescription": "O usuário foi criado com sucesso.",
|
||||
"userTypeInternal": "Usuário Interno",
|
||||
"userTypeInternalDescription": "Convidar um usuário para se juntar à sua organização diretamente.",
|
||||
"userTypeExternal": "Usuário Externo",
|
||||
"userTypeExternalDescription": "Criar um usuário com um provedor de identidade externo.",
|
||||
"accessUserCreateDescription": "Siga os passos abaixo para criar um novo usuário",
|
||||
"userSeeAll": "Ver Todos os Usuários",
|
||||
"userTypeTitle": "Tipo de Usuário",
|
||||
"userTypeDescription": "Determine como você deseja criar o usuário",
|
||||
"userSettings": "Informações do Usuário",
|
||||
"userSettingsDescription": "Insira os detalhes para o novo usuário",
|
||||
"inviteEmailSent": "Enviar e-mail de convite para o usuário",
|
||||
"inviteValid": "Válido Por",
|
||||
"selectDuration": "Selecionar duração",
|
||||
"accessRoleSelect": "Selecionar função",
|
||||
"inviteEmailSentDescription": "Um e-mail foi enviado ao usuário com o link de acesso abaixo. Eles devem acessar o link para aceitar o convite.",
|
||||
"inviteSentDescription": "O usuário foi convidado. Eles devem acessar o link abaixo para aceitar o convite.",
|
||||
"inviteExpiresIn": "O convite expirará em <b>{days, plural, =1 {# dia} other {# dias}}</b>.",
|
||||
"idpTitle": "Provedor de Identidade",
|
||||
"idpSelect": "Selecione o provedor de identidade para o usuário externo",
|
||||
"idpNotConfigured": "Nenhum provedor de identidade está configurado. Configure um provedor de identidade antes de criar usuários externos.",
|
||||
"usernameUniq": "Isto deve corresponder ao nome de usuário único que existe no provedor de identidade selecionado.",
|
||||
"emailOptional": "E-mail (Opcional)",
|
||||
"nameOptional": "Nome (Opcional)",
|
||||
"accessControls": "Controles de Acesso",
|
||||
"userDescription2": "Gerenciar as configurações deste usuário",
|
||||
"accessRoleErrorAdd": "Falha ao adicionar usuário à função",
|
||||
"accessRoleErrorAddDescription": "Ocorreu um erro ao adicionar usuário à função.",
|
||||
"userSaved": "Usuário salvo",
|
||||
"userSavedDescription": "O usuário foi atualizado.",
|
||||
"accessControlsDescription": "Gerencie o que este usuário pode acessar e fazer na organização",
|
||||
"accessControlsSubmit": "Salvar Controles de Acesso",
|
||||
"roles": "Funções",
|
||||
"accessUsersRoles": "Gerenciar Usuários e Funções",
|
||||
"accessUsersRolesDescription": "Convide usuários e adicione-os a funções para gerenciar o acesso à sua organização",
|
||||
"key": "Chave",
|
||||
"createdAt": "Criado Em",
|
||||
"proxyErrorInvalidHeader": "Valor do cabeçalho Host personalizado inválido. Use o formato de nome de domínio ou salve vazio para remover o cabeçalho Host personalizado.",
|
||||
"proxyErrorTls": "Nome do Servidor TLS inválido. Use o formato de nome de domínio ou salve vazio para remover o Nome do Servidor TLS.",
|
||||
"targetErrorFetch": "Falha ao buscar alvos",
|
||||
"targetErrorFetchDescription": "Ocorreu um erro ao buscar alvos",
|
||||
"siteErrorFetch": "Falha ao buscar recurso",
|
||||
"siteErrorFetchDescription": "Ocorreu um erro ao buscar recurso",
|
||||
"targetErrorDuplicate": "Alvo duplicado",
|
||||
"targetErrorDuplicateDescription": "Um alvo com estas configurações já existe",
|
||||
"targetWireGuardErrorInvalidIp": "IP do alvo inválido",
|
||||
"targetWireGuardErrorInvalidIpDescription": "O IP do alvo deve estar dentro da subnet do site",
|
||||
"targetsUpdated": "Alvos atualizados",
|
||||
"targetsUpdatedDescription": "Alvos e configurações atualizados com sucesso",
|
||||
"targetsErrorUpdate": "Falha ao atualizar alvos",
|
||||
"targetsErrorUpdateDescription": "Ocorreu um erro ao atualizar alvos",
|
||||
"targetTlsUpdate": "Configurações TLS atualizadas",
|
||||
"targetTlsUpdateDescription": "Suas configurações TLS foram atualizadas com sucesso",
|
||||
"targetErrorTlsUpdate": "Falha ao atualizar configurações TLS",
|
||||
"targetErrorTlsUpdateDescription": "Ocorreu um erro ao atualizar as configurações TLS",
|
||||
"proxyUpdated": "Configurações de proxy atualizadas",
|
||||
"proxyUpdatedDescription": "Suas configurações de proxy foram atualizadas com sucesso",
|
||||
"proxyErrorUpdate": "Falha ao atualizar configurações de proxy",
|
||||
"proxyErrorUpdateDescription": "Ocorreu um erro ao atualizar as configurações de proxy",
|
||||
"targetAddr": "IP / Nome do Host",
|
||||
"targetPort": "Porta",
|
||||
"targetProtocol": "Protocolo",
|
||||
"targetTlsSettings": "Configurações HTTPS & TLS",
|
||||
"targetTlsSettingsDescription": "Configure as configurações TLS para seu recurso",
|
||||
"targetTlsSettingsAdvanced": "Configurações TLS Avançadas",
|
||||
"targetTlsSni": "Nome do Servidor TLS (SNI)",
|
||||
"targetTlsSniDescription": "O Nome do Servidor TLS para usar para SNI. Deixe vazio para usar o padrão.",
|
||||
"targetTlsSubmit": "Salvar Configurações",
|
||||
"targets": "Configuração de Alvos",
|
||||
"targetsDescription": "Configure alvos para rotear tráfego para seus serviços",
|
||||
"targetStickySessions": "Ativar Sessões Persistentes",
|
||||
"targetStickySessionsDescription": "Manter conexões no mesmo alvo backend durante toda a sessão.",
|
||||
"methodSelect": "Selecionar método",
|
||||
"targetSubmit": "Adicionar Alvo",
|
||||
"targetNoOne": "Sem alvos. Adicione um alvo usando o formulário.",
|
||||
"targetNoOneDescription": "Adicionar mais de um alvo acima habilitará o balanceamento de carga.",
|
||||
"targetsSubmit": "Salvar Alvos",
|
||||
"proxyAdditional": "Configurações Adicionais de Proxy",
|
||||
"proxyAdditionalDescription": "Configure como seu recurso lida com configurações de proxy",
|
||||
"proxyCustomHeader": "Cabeçalho Host Personalizado",
|
||||
"proxyCustomHeaderDescription": "O cabeçalho host para definir ao fazer proxy de requisições. Deixe vazio para usar o padrão.",
|
||||
"proxyAdditionalSubmit": "Salvar Configurações de Proxy",
|
||||
"subnetMaskErrorInvalid": "Máscara de subnet inválida. Deve estar entre 0 e 32.",
|
||||
"ipAddressErrorInvalidFormat": "Formato de endereço IP inválido",
|
||||
"ipAddressErrorInvalidOctet": "Octeto de endereço IP inválido",
|
||||
"path": "Caminho",
|
||||
"ipAddressRange": "Faixa de IP",
|
||||
"rulesErrorFetch": "Falha ao buscar regras",
|
||||
"rulesErrorFetchDescription": "Ocorreu um erro ao buscar regras",
|
||||
"rulesErrorDuplicate": "Regra duplicada",
|
||||
"rulesErrorDuplicateDescription": "Uma regra com estas configurações já existe",
|
||||
"rulesErrorInvalidIpAddressRange": "CIDR inválido",
|
||||
"rulesErrorInvalidIpAddressRangeDescription": "Por favor, insira um valor CIDR válido",
|
||||
"rulesErrorInvalidUrl": "Caminho URL inválido",
|
||||
"rulesErrorInvalidUrlDescription": "Por favor, insira um valor de caminho URL válido",
|
||||
"rulesErrorInvalidIpAddress": "IP inválido",
|
||||
"rulesErrorInvalidIpAddressDescription": "Por favor, insira um endereço IP válido",
|
||||
"rulesErrorUpdate": "Falha ao atualizar regras",
|
||||
"rulesErrorUpdateDescription": "Ocorreu um erro ao atualizar regras",
|
||||
"rulesUpdated": "Ativar Regras",
|
||||
"rulesUpdatedDescription": "A avaliação de regras foi atualizada",
|
||||
"rulesMatchIpAddressRangeDescription": "Insira um endereço no formato CIDR (ex: 103.21.244.0/22)",
|
||||
"rulesMatchIpAddress": "Insira um endereço IP (ex: 103.21.244.12)",
|
||||
"rulesMatchUrl": "Insira um caminho URL ou padrão (ex: /api/v1/todos ou /api/v1/*)",
|
||||
"rulesErrorInvalidPriority": "Prioridade Inválida",
|
||||
"rulesErrorInvalidPriorityDescription": "Por favor, insira uma prioridade válida",
|
||||
"rulesErrorDuplicatePriority": "Prioridades Duplicadas",
|
||||
"rulesErrorDuplicatePriorityDescription": "Por favor, insira prioridades únicas",
|
||||
"ruleUpdated": "Regras atualizadas",
|
||||
"ruleUpdatedDescription": "Regras atualizadas com sucesso",
|
||||
"ruleErrorUpdate": "Operação falhou",
|
||||
"ruleErrorUpdateDescription": "Ocorreu um erro durante a operação de salvamento",
|
||||
"rulesPriority": "Prioridade",
|
||||
"rulesAction": "Ação",
|
||||
"rulesMatchType": "Tipo de Correspondência",
|
||||
"value": "Valor",
|
||||
"rulesAbout": "Sobre Regras",
|
||||
"rulesAboutDescription": "As regras permitem controlar o acesso ao seu recurso com base em um conjunto de critérios. Você pode criar regras para permitir ou negar acesso com base no endereço IP ou caminho URL.",
|
||||
"rulesActions": "Ações",
|
||||
"rulesActionAlwaysAllow": "Sempre Permitir: Ignorar todos os métodos de autenticação",
|
||||
"rulesActionAlwaysDeny": "Sempre Negar: Bloquear todas as requisições; nenhuma autenticação pode ser tentada",
|
||||
"rulesMatchCriteria": "Critérios de Correspondência",
|
||||
"rulesMatchCriteriaIpAddress": "Corresponder a um endereço IP específico",
|
||||
"rulesMatchCriteriaIpAddressRange": "Corresponder a uma faixa de endereços IP em notação CIDR",
|
||||
"rulesMatchCriteriaUrl": "Corresponder a um caminho URL ou padrão",
|
||||
"rulesEnable": "Ativar Regras",
|
||||
"rulesEnableDescription": "Ativar ou desativar avaliação de regras para este recurso",
|
||||
"rulesResource": "Configuração de Regras do Recurso",
|
||||
"rulesResourceDescription": "Configure regras para controlar o acesso ao seu recurso",
|
||||
"ruleSubmit": "Adicionar Regra",
|
||||
"rulesNoOne": "Sem regras. Adicione uma regra usando o formulário.",
|
||||
"rulesOrder": "As regras são avaliadas por prioridade em ordem ascendente.",
|
||||
"rulesSubmit": "Salvar Regras",
|
||||
"resourceErrorCreate": "Erro ao criar recurso",
|
||||
"resourceErrorCreateDescription": "Ocorreu um erro ao criar o recurso",
|
||||
"resourceErrorCreateMessage": "Erro ao criar recurso:",
|
||||
"resourceErrorCreateMessageDescription": "Ocorreu um erro inesperado",
|
||||
"sitesErrorFetch": "Erro ao buscar sites",
|
||||
"sitesErrorFetchDescription": "Ocorreu um erro ao buscar os sites",
|
||||
"domainsErrorFetch": "Erro ao buscar domínios",
|
||||
"domainsErrorFetchDescription": "Ocorreu um erro ao buscar os domínios",
|
||||
"none": "Nenhum",
|
||||
"unknown": "Desconhecido",
|
||||
"resources": "Recursos",
|
||||
"resourcesDescription": "Recursos são proxies para aplicações executando em sua rede privada. Crie um recurso para qualquer serviço HTTP/HTTPS ou TCP/UDP bruto em sua rede privada. Cada recurso deve estar conectado a um site para habilitar conectividade privada e segura através de um túnel WireGuard criptografado.",
|
||||
"resourcesWireGuardConnect": "Conectividade segura com criptografia WireGuard",
|
||||
"resourcesMultipleAuthenticationMethods": "Configure múltiplos métodos de autenticação",
|
||||
"resourcesUsersRolesAccess": "Controle de acesso baseado em usuários e funções",
|
||||
"resourcesErrorUpdate": "Falha ao alternar recurso",
|
||||
"resourcesErrorUpdateDescription": "Ocorreu um erro ao atualizar o recurso",
|
||||
"access": "Acesso",
|
||||
"shareLink": "Link de Compartilhamento {resource}",
|
||||
"resourceSelect": "Selecionar recurso",
|
||||
"shareLinks": "Links de Compartilhamento",
|
||||
"share": "Links Compartilháveis",
|
||||
"shareDescription2": "Crie links compartilháveis para seus recursos. Os links fornecem acesso temporário ou ilimitado ao seu recurso. Você pode configurar a duração da expiração do link quando o criar.",
|
||||
"shareEasyCreate": "Fácil de criar e compartilhar",
|
||||
"shareConfigurableExpirationDuration": "Duração de expiração configurável",
|
||||
"shareSecureAndRevocable": "Seguro e revogável",
|
||||
"nameMin": "O nome deve ter pelo menos {len} caracteres.",
|
||||
"nameMax": "O nome não deve ter mais que {len} caracteres.",
|
||||
"sitesConfirmCopy": "Por favor, confirme que você copiou a configuração.",
|
||||
"unknownCommand": "Comando desconhecido",
|
||||
"newtErrorFetchReleases": "Falha ao buscar informações da versão: {err}",
|
||||
"newtErrorFetchLatest": "Erro ao buscar última versão: {err}",
|
||||
"newtEndpoint": "Endpoint Newt",
|
||||
"newtId": "ID Newt",
|
||||
"newtSecretKey": "Chave Secreta Newt",
|
||||
"architecture": "Arquitetura",
|
||||
"sites": "Sites",
|
||||
"siteWgAnyClients": "Use qualquer cliente WireGuard para conectar. Você terá que endereçar seus recursos internos usando o IP do par.",
|
||||
"siteWgCompatibleAllClients": "Compatível com todos os clientes WireGuard",
|
||||
"siteWgManualConfigurationRequired": "Configuração manual necessária",
|
||||
"userErrorNotAdminOrOwner": "Usuário não é administrador ou proprietário",
|
||||
"pangolinSettings": "Configurações - Pangolin",
|
||||
"accessRoleYour": "Sua função:",
|
||||
"accessRoleSelect2": "Selecionar uma função",
|
||||
"accessUserSelect": "Selecionar um usuário",
|
||||
"otpEmailEnter": "Digite um e-mail",
|
||||
"otpEmailEnterDescription": "Pressione enter para adicionar um e-mail após digitá-lo no campo de entrada.",
|
||||
"otpEmailErrorInvalid": "Endereço de e-mail inválido. O caractere curinga (*) deve ser a parte local inteira.",
|
||||
"otpEmailSmtpRequired": "SMTP Necessário",
|
||||
"otpEmailSmtpRequiredDescription": "O SMTP deve estar habilitado no servidor para usar a autenticação de senha única.",
|
||||
"otpEmailTitle": "Senhas Únicas",
|
||||
"otpEmailTitleDescription": "Requer autenticação baseada em e-mail para acesso ao recurso",
|
||||
"otpEmailWhitelist": "Lista de E-mails Permitidos",
|
||||
"otpEmailWhitelistList": "E-mails na Lista Permitida",
|
||||
"otpEmailWhitelistListDescription": "Apenas usuários com estes endereços de e-mail poderão acessar este recurso. Eles serão solicitados a inserir uma senha única enviada para seu e-mail. Caracteres curinga (*@example.com) podem ser usados para permitir qualquer endereço de e-mail de um domínio.",
|
||||
"otpEmailWhitelistSave": "Salvar Lista Permitida",
|
||||
"passwordAdd": "Adicionar Senha",
|
||||
"passwordRemove": "Remover Senha",
|
||||
"pincodeAdd": "Adicionar Código PIN",
|
||||
"pincodeRemove": "Remover Código PIN",
|
||||
"resourceAuthMethods": "Métodos de Autenticação",
|
||||
"resourceAuthMethodsDescriptions": "Permitir acesso ao recurso via métodos de autenticação adicionais",
|
||||
"resourceAuthSettingsSave": "Salvo com sucesso",
|
||||
"resourceAuthSettingsSaveDescription": "As configurações de autenticação foram salvas",
|
||||
"resourceErrorAuthFetch": "Falha ao buscar dados",
|
||||
"resourceErrorAuthFetchDescription": "Ocorreu um erro ao buscar os dados",
|
||||
"resourceErrorPasswordRemove": "Erro ao remover senha do recurso",
|
||||
"resourceErrorPasswordRemoveDescription": "Ocorreu um erro ao remover a senha do recurso",
|
||||
"resourceErrorPasswordSetup": "Erro ao definir senha do recurso",
|
||||
"resourceErrorPasswordSetupDescription": "Ocorreu um erro ao definir a senha do recurso",
|
||||
"resourceErrorPincodeRemove": "Erro ao remover código PIN do recurso",
|
||||
"resourceErrorPincodeRemoveDescription": "Ocorreu um erro ao remover o código PIN do recurso",
|
||||
"resourceErrorPincodeSetup": "Erro ao definir código PIN do recurso",
|
||||
"resourceErrorPincodeSetupDescription": "Ocorreu um erro ao definir o código PIN do recurso",
|
||||
"resourceErrorUsersRolesSave": "Falha ao definir funções",
|
||||
"resourceErrorUsersRolesSaveDescription": "Ocorreu um erro ao definir as funções",
|
||||
"resourceErrorWhitelistSave": "Falha ao salvar lista permitida",
|
||||
"resourceErrorWhitelistSaveDescription": "Ocorreu um erro ao salvar a lista permitida",
|
||||
"resourcePasswordSubmit": "Habilitar Proteção por Senha",
|
||||
"resourcePasswordRemove": "Senha do recurso removida",
|
||||
"resourcePasswordRemoveDescription": "A senha do recurso foi removida com sucesso",
|
||||
"resourcePasswordSetup": "Senha do recurso definida",
|
||||
"resourcePasswordSetupDescription": "A senha do recurso foi definida com sucesso",
|
||||
"resourcePasswordSetupTitle": "Definir Senha",
|
||||
"resourcePasswordSetupTitleDescription": "Defina uma senha para proteger este recurso",
|
||||
"resourcePincode": "Código PIN",
|
||||
"resourcePincodeSubmit": "Habilitar Proteção por Código PIN",
|
||||
"resourcePincodeProtection": "Proteção por Código PIN {status}",
|
||||
"resourcePincodeRemove": "Código PIN do recurso removido",
|
||||
"resourcePincodeRemoveDescription": "O código PIN do recurso foi removido com sucesso",
|
||||
"resourcePincodeSetup": "Código PIN do recurso definido",
|
||||
"resourcePincodeSetupDescription": "O código PIN do recurso foi definido com sucesso",
|
||||
"resourcePincodeSetupTitle": "Definir Código PIN",
|
||||
"resourcePincodeSetupTitleDescription": "Defina um código PIN para proteger este recurso",
|
||||
"resourceRoleDescription": "Administradores sempre podem acessar este recurso.",
|
||||
"resourceUsersRoles": "Usuários e Funções",
|
||||
"resourceUsersRolesDescription": "Configure quais usuários e funções podem visitar este recurso",
|
||||
"resourceUsersRolesSubmit": "Salvar Usuários e Funções",
|
||||
"resourceWhitelistSave": "Salvo com sucesso",
|
||||
"resourceWhitelistSaveDescription": "As configurações da lista permitida foram salvas",
|
||||
"ssoUse": "Usar SSO da Plataforma",
|
||||
"ssoUseDescription": "Os usuários existentes só precisarão fazer login uma vez para todos os recursos que tiverem isso habilitado.",
|
||||
"proxyErrorInvalidPort": "Número da porta inválido",
|
||||
"subdomainErrorInvalid": "Subdomínio inválido",
|
||||
"domainErrorFetch": "Erro ao buscar domínios",
|
||||
"domainErrorFetchDescription": "Ocorreu um erro ao buscar os domínios",
|
||||
"resourceErrorUpdate": "Falha ao atualizar recurso",
|
||||
"resourceErrorUpdateDescription": "Ocorreu um erro ao atualizar o recurso",
|
||||
"resourceUpdated": "Recurso atualizado",
|
||||
"resourceUpdatedDescription": "O recurso foi atualizado com sucesso",
|
||||
"resourceErrorTransfer": "Falha ao transferir recurso",
|
||||
"resourceErrorTransferDescription": "Ocorreu um erro ao transferir o recurso",
|
||||
"resourceTransferred": "Recurso transferido",
|
||||
"resourceTransferredDescription": "O recurso foi transferido com sucesso",
|
||||
"resourceErrorToggle": "Falha ao alternar recurso",
|
||||
"resourceErrorToggleDescription": "Ocorreu um erro ao atualizar o recurso",
|
||||
"resourceVisibilityTitle": "Visibilidade",
|
||||
"resourceVisibilityTitleDescription": "Ativar ou desativar completamente a visibilidade do recurso",
|
||||
"resourceGeneral": "Configurações Gerais",
|
||||
"resourceGeneralDescription": "Configure as configurações gerais para este recurso",
|
||||
"resourceEnable": "Ativar Recurso",
|
||||
"resourceTransfer": "Transferir Recurso",
|
||||
"resourceTransferDescription": "Transferir este recurso para um site diferente",
|
||||
"resourceTransferSubmit": "Transferir Recurso",
|
||||
"siteDestination": "Site de Destino",
|
||||
"searchSites": "Pesquisar sites",
|
||||
"accessRoleCreate": "Criar Função",
|
||||
"accessRoleCreateDescription": "Crie uma nova função para agrupar usuários e gerenciar suas permissões.",
|
||||
"accessRoleCreateSubmit": "Criar Função",
|
||||
"accessRoleCreated": "Função criada",
|
||||
"accessRoleCreatedDescription": "A função foi criada com sucesso.",
|
||||
"accessRoleErrorCreate": "Falha ao criar função",
|
||||
"accessRoleErrorCreateDescription": "Ocorreu um erro ao criar a função.",
|
||||
"accessRoleErrorNewRequired": "Nova função é necessária",
|
||||
"accessRoleErrorRemove": "Falha ao remover função",
|
||||
"accessRoleErrorRemoveDescription": "Ocorreu um erro ao remover a função.",
|
||||
"accessRoleName": "Nome da Função",
|
||||
"accessRoleQuestionRemove": "Você está prestes a excluir a função <b>{name}</b>. Você não pode desfazer esta ação.",
|
||||
"accessRoleRemove": "Remover Função",
|
||||
"accessRoleRemoveDescription": "Remover uma função da organização",
|
||||
"accessRoleRemoveSubmit": "Remover Função",
|
||||
"accessRoleRemoved": "Função removida",
|
||||
"accessRoleRemovedDescription": "A função foi removida com sucesso.",
|
||||
"accessRoleRequiredRemove": "Antes de excluir esta função, selecione uma nova função para transferir os membros existentes.",
|
||||
"manage": "Gerir",
|
||||
"sitesNotFound": "Nenhum site encontrado."
|
||||
}
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
"siteCreateDescription2": "Follow the steps below to create and connect a new site",
|
||||
"siteCreateDescription": "Create a new site to start connecting your resources",
|
||||
"close": "Close",
|
||||
"siteNameMin": "Name must be at least 2 characters.",
|
||||
"siteNameMax": "Name must not be longer than 30 characters.",
|
||||
"siteErrorCreate": "Error creating site",
|
||||
"siteErrorCreateKeyPair": "Key pair or site defaults not found",
|
||||
"siteErrorCreateDefaults": "Site defaults not found",
|
||||
|
@ -71,7 +69,7 @@
|
|||
"dockerRun": "Docker Run",
|
||||
"siteLearnLocal": "Local sites do not tunnel, learn more",
|
||||
"siteConfirmCopy": "I have copied the config",
|
||||
"searchSites": "Search sites...",
|
||||
"searchSitesProgress": "Search sites...",
|
||||
"siteAdd": "Add Site",
|
||||
"siteInstallNewt": "Install Newt",
|
||||
"siteInstallNewtDescription": "Get Newt running on your system",
|
||||
|
@ -111,7 +109,7 @@
|
|||
"shareErrorDelete": "Failed to delete link",
|
||||
"shareErrorDeleteMessage": "An error occurred deleting link",
|
||||
"shareDeleted": "Link deleted",
|
||||
"shareDeletedDesciption": "The link has been deleted",
|
||||
"shareDeletedDescription": "The link has been deleted",
|
||||
"shareTokenDescription": "Your access token can be passed in two ways: as a query parameter or in the request headers. These must be passed from the client on every request for authenticated access.",
|
||||
"accessToken": "Access Token",
|
||||
"usageExamples": "Usage Examples",
|
||||
|
@ -234,7 +232,7 @@
|
|||
"username": "Username",
|
||||
"identityProvider": "Identity Provider",
|
||||
"role": "Role",
|
||||
"accessRoleNameRequired": "Name is required",
|
||||
"nameRequired": "Name is required",
|
||||
"accessRolesManage": "Manage Roles",
|
||||
"accessRolesDescription": "Configure roles to manage access to your organization",
|
||||
"accessRolesSearch": "Search roles...",
|
||||
|
@ -252,8 +250,6 @@
|
|||
"years": "Years",
|
||||
"day": "{count, plural, =1 {# day} other {# days}}",
|
||||
"apiKeysTitle": "API Key Information",
|
||||
"apiKeysNameMin": "Name must be at least 2 characters.",
|
||||
"apiKeysNameMax": "Name must not be longer than 255 characters.",
|
||||
"apiKeysConfirmCopy2": "You must confirm that you have copied the API key.",
|
||||
"apiKeysErrorCreate": "Error creating API key",
|
||||
"apiKeysErrorSetPermission": "Error setting permissions",
|
||||
|
@ -363,10 +359,10 @@
|
|||
"inviteRemoveErrorDescription": "An error occurred while removing the invitation.",
|
||||
"inviteRemoved": "Invitation removed",
|
||||
"inviteRemovedDescription": "The invitation for {email} has been removed.",
|
||||
"inviteQuestionRemove": "Are you sure you want to remove the invitation{email, plural, ='' {}, other { for #}}?",
|
||||
"inviteQuestionRemove": "Are you sure you want to remove the invitation {email}?",
|
||||
"inviteMessageRemove": "Once removed, this invitation will no longer be valid. You can always re-invite the user later.",
|
||||
"inviteMessageConfirm": "To confirm, please type the email address of the invitation below.",
|
||||
"inviteQuestionRegenerate": "Are you sure you want to regenerate the invitation for{email, plural, ='' {}, other { for #}}? This will revoke the previous invitation.",
|
||||
"inviteQuestionRegenerate": "Are you sure you want to regenerate the invitation for {email}? This will revoke the previous invitation.",
|
||||
"inviteRemoveConfirm": "Confirm Remove Invitation",
|
||||
"inviteRegenerated": "Invitation Regenerated",
|
||||
"inviteSent": "A new invitation has been sent to {email}.",
|
||||
|
@ -382,5 +378,319 @@
|
|||
"inviteValidityPeriodSelect": "Select validity period",
|
||||
"inviteRegenerateMessage": "The invitation has been regenerated. The user must access the link below to accept the invitation.",
|
||||
"inviteRegenerateButton": "Regenerate",
|
||||
"expiresAt": "Expires At"
|
||||
"expiresAt": "Expires At",
|
||||
"accessRoleUnknown": "Unknown Role",
|
||||
"placeholder": "Placeholder",
|
||||
"userErrorOrgRemove": "Failed to remove user",
|
||||
"userErrorOrgRemoveDescription": "An error occurred while removing the user.",
|
||||
"userOrgRemoved": "User removed",
|
||||
"userOrgRemovedDescription": "The user {email} has been removed from the organization.",
|
||||
"userQuestionOrgRemove": "Are you sure you want to remove <b>{email}</b> from the organization?",
|
||||
"userMessageOrgRemove": "Once removed, this user will no longer have access to the organization. You can always re-invite them later, but they will need to accept the invitation again.",
|
||||
"userMessageOrgConfirm": "To confirm, please type the name of the of the user below.",
|
||||
"userRemoveOrgConfirm": "Confirm Remove User",
|
||||
"userRemoveOrg": "Remove User from Organization",
|
||||
"users": "Users",
|
||||
"accessRoleMember": "Member",
|
||||
"accessRoleOwner": "Owner",
|
||||
"userConfirmed": "Confirmed",
|
||||
"idpNameInternal": "Internal",
|
||||
"emailInvalid": "Invalid email address",
|
||||
"inviteValidityDuration": "Please select a duration",
|
||||
"accessRoleSelectPlease": "Please select a role",
|
||||
"usernameRequired": "Username is required",
|
||||
"idpSelectPlease": "Please select an identity provider",
|
||||
"idpGenericOidc": "Generic OAuth2/OIDC provider.",
|
||||
"accessRoleErrorFetch": "Failed to fetch roles",
|
||||
"accessRoleErrorFetchDescription": "An error occurred while fetching the roles",
|
||||
"idpErrorFetch": "Failed to fetch identity providers",
|
||||
"idpErrorFetchDescription": "An error occurred while fetching identity providers",
|
||||
"userErrorExists": "User Already Exists",
|
||||
"userErrorExistsDescription": "This user is already a member of the organization.",
|
||||
"inviteError": "Failed to invite user",
|
||||
"inviteErrorDescription": "An error occurred while inviting the user",
|
||||
"userInvited": "User invited",
|
||||
"userInvitedDescription": "The user has been successfully invited.",
|
||||
"userErrorCreate": "Failed to create user",
|
||||
"userErrorCreateDescription": "An error occurred while creating the user",
|
||||
"userCreated": "User created",
|
||||
"userCreatedDescription": "The user has been successfully created.",
|
||||
"userTypeInternal": "Internal User",
|
||||
"userTypeInternalDescription": "Invite a user to join your organization directly.",
|
||||
"userTypeExternal": "External User",
|
||||
"userTypeExternalDescription": "Create a user with an external identity provider.",
|
||||
"accessUserCreateDescription": "Follow the steps below to create a new user",
|
||||
"userSeeAll": "See All Users",
|
||||
"userTypeTitle": "User Type",
|
||||
"userTypeDescription": "Determine how you want to create the user",
|
||||
"userSettings": "User Information",
|
||||
"userSettingsDescription": "Enter the details for the new user",
|
||||
"inviteEmailSent": "Send invite email to user",
|
||||
"inviteValid": "Valid For",
|
||||
"selectDuration": "Select duration",
|
||||
"accessRoleSelect": "Select role",
|
||||
"inviteEmailSentDescription": "An email has been sent to the user with the access link below. They must access the link to accept the invitation.",
|
||||
"inviteSentDescription": "The user has been invited. They must access the link below to accept the invitation.",
|
||||
"inviteExpiresIn": "The invite will expire in <b>{days, plural, =1 {# day} other {# days}}</b>.",
|
||||
"idpTitle": "Identity Provider",
|
||||
"idpSelect": "Select the identity provider for the external user",
|
||||
"idpNotConfigured": "No identity providers are configured. Please configure an identity provider before creating external users.",
|
||||
"usernameUniq": "This must match the unique username that exists in the selected identity provider.",
|
||||
"emailOptional": "Email (Optional)",
|
||||
"nameOptional": "Name (Optional)",
|
||||
"accessControls": "Access Controls",
|
||||
"userDescription2": "Manage the settings on this user",
|
||||
"accessRoleErrorAdd": "Failed to add user to role",
|
||||
"accessRoleErrorAddDescription": "An error occurred while adding user to the role.",
|
||||
"userSaved": "User saved",
|
||||
"userSavedDescription": "The user has been updated.",
|
||||
"accessControlsDescription": "Manage what this user can access and do in the organization",
|
||||
"accessControlsSubmit": "Save Access Controls",
|
||||
"roles": "Roles",
|
||||
"accessUsersRoles": "Manage Users & Roles",
|
||||
"accessUsersRolesDescription": "Invite users and add them to roles to manage access to your organization",
|
||||
"key": "Key",
|
||||
"createdAt": "Created At",
|
||||
"proxyErrorInvalidHeader": "Invalid custom Host Header value. Use domain name format, or save empty to unset custom Host Header.",
|
||||
"proxyErrorTls": "Invalid TLS Server Name. Use domain name format, or save empty to remove the TLS Server Name.",
|
||||
"targetErrorFetch": "Failed to fetch targets",
|
||||
"targetErrorFetchDescription": "An error occurred while fetching targets",
|
||||
"siteErrorFetch": "Failed to fetch resource",
|
||||
"siteErrorFetchDescription": "An error occurred while fetching resource",
|
||||
"targetErrorDuplicate": "Duplicate target",
|
||||
"targetErrorDuplicateDescription": "A target with these settings already exists",
|
||||
"targetWireGuardErrorInvalidIp": "Invalid target IP",
|
||||
"targetWireGuardErrorInvalidIpDescription": "Target IP must be within the site subnet",
|
||||
"targetsUpdated": "Targets updated",
|
||||
"targetsUpdatedDescription": "Targets and settings updated successfully",
|
||||
"targetsErrorUpdate": "Failed to update targets",
|
||||
"targetsErrorUpdateDescription": "An error occurred while updating targets",
|
||||
"targetTlsUpdate": "TLS settings updated",
|
||||
"targetTlsUpdateDescription": "Your TLS settings have been updated successfully",
|
||||
"targetErrorTlsUpdate": "Failed to update TLS settings",
|
||||
"targetErrorTlsUpdateDescription": "An error occurred while updating TLS settings",
|
||||
"proxyUpdated": "Proxy settings updated",
|
||||
"proxyUpdatedDescription": "Your proxy settings have been updated successfully",
|
||||
"proxyErrorUpdate": "Failed to update proxy settings",
|
||||
"proxyErrorUpdateDescription": "An error occurred while updating proxy settings",
|
||||
"targetAddr": "IP / Hostname",
|
||||
"targetPort": "Port",
|
||||
"targetProtocol": "Protocol",
|
||||
"targetTlsSettings": "HTTPS & TLS Settings",
|
||||
"targetTlsSettingsDescription": "Configure TLS settings for your resource",
|
||||
"targetTlsSettingsAdvanced": "Advanced TLS Settings",
|
||||
"targetTlsSni": "TLS Server Name (SNI)",
|
||||
"targetTlsSniDescription": "The TLS Server Name to use for SNI. Leave empty to use the default.",
|
||||
"targetTlsSubmit": "Save Settings",
|
||||
"targets": "Targets Configuration",
|
||||
"targetsDescription": "Set up targets to route traffic to your services",
|
||||
"targetStickySessions": "Enable Sticky Sessions",
|
||||
"targetStickySessionsDescription": "Keep connections on the same backend target for their entire session.",
|
||||
"methodSelect": "Select method",
|
||||
"targetSubmit": "Add Target",
|
||||
"targetNoOne": "No targets. Add a target using the form.",
|
||||
"targetNoOneDescription": "Adding more than one target above will enable load balancing.",
|
||||
"targetsSubmit": "Save Targets",
|
||||
"proxyAdditional": "Additional Proxy Settings",
|
||||
"proxyAdditionalDescription": "Configure how your resource handles proxy settings",
|
||||
"proxyCustomHeader": "Custom Host Header",
|
||||
"proxyCustomHeaderDescription": "The host header to set when proxying requests. Leave empty to use the default.",
|
||||
"proxyAdditionalSubmit": "Save Proxy Settings",
|
||||
"subnetMaskErrorInvalid": "Invalid subnet mask. Must be between 0 and 32.",
|
||||
"ipAddressErrorInvalidFormat": "Invalid IP address format",
|
||||
"ipAddressErrorInvalidOctet": "Invalid IP address octet",
|
||||
"path": "Path",
|
||||
"ipAddressRange": "IP Range",
|
||||
"rulesErrorFetch": "Failed to fetch rules",
|
||||
"rulesErrorFetchDescription": "An error occurred while fetching rules",
|
||||
"rulesErrorDuplicate": "Duplicate rule",
|
||||
"rulesErrorDuplicateDescription": "A rule with these settings already exists",
|
||||
"rulesErrorInvalidIpAddressRange": "Invalid CIDR",
|
||||
"rulesErrorInvalidIpAddressRangeDescription": "Please enter a valid CIDR value",
|
||||
"rulesErrorInvalidUrl": "Invalid URL path",
|
||||
"rulesErrorInvalidUrlDescription": "Please enter a valid URL path value",
|
||||
"rulesErrorInvalidIpAddress": "Invalid IP",
|
||||
"rulesErrorInvalidIpAddressDescription": "Please enter a valid IP address",
|
||||
"rulesErrorUpdate": "Failed to update rules",
|
||||
"rulesErrorUpdateDescription": "An error occurred while updating rules",
|
||||
"rulesUpdated": "Enable Rules",
|
||||
"rulesUpdatedDescription": "Rule evaluation has been updated",
|
||||
"rulesMatchIpAddressRangeDescription": "Enter an address in CIDR format (e.g., 103.21.244.0/22)",
|
||||
"rulesMatchIpAddress": "Enter an IP address (e.g., 103.21.244.12)",
|
||||
"rulesMatchUrl": "Enter a URL path or pattern (e.g., /api/v1/todos or /api/v1/*)",
|
||||
"rulesErrorInvalidPriority": "Invalid Priority",
|
||||
"rulesErrorInvalidPriorityDescription": "Please enter a valid priority",
|
||||
"rulesErrorDuplicatePriority": "Duplicate Priorities",
|
||||
"rulesErrorDuplicatePriorityDescription": "Please enter unique priorities",
|
||||
"ruleUpdated": "Rules updated",
|
||||
"ruleUpdatedDescription": "Rules updated successfully",
|
||||
"ruleErrorUpdate": "Operation failed",
|
||||
"ruleErrorUpdateDescription": "An error occurred during the save operation",
|
||||
"rulesPriority": "Priority",
|
||||
"rulesAction": "Action",
|
||||
"rulesMatchType": "Match Type",
|
||||
"value": "Value",
|
||||
"rulesAbout": "About Rules",
|
||||
"rulesAboutDescription": "Rules allow you to control access to your resource based on a set of criteria. You can create rules to allow or deny access based on IP address or URL path.",
|
||||
"rulesActions": "Actions",
|
||||
"rulesActionAlwaysAllow": "Always Allow: Bypass all authentication methods",
|
||||
"rulesActionAlwaysDeny": "Always Deny: Block all requests; no authentication can be attempted",
|
||||
"rulesMatchCriteria": "Matching Criteria",
|
||||
"rulesMatchCriteriaIpAddress": "Match a specific IP address",
|
||||
"rulesMatchCriteriaIpAddressRange": "Match a range of IP addresses in CIDR notation",
|
||||
"rulesMatchCriteriaUrl": "Match a URL path or pattern",
|
||||
"rulesEnable": "Enable Rules",
|
||||
"rulesEnableDescription": "Enable or disable rule evaluation for this resource",
|
||||
"rulesResource": "Resource Rules Configuration",
|
||||
"rulesResourceDescription": "Configure rules to control access to your resource",
|
||||
"ruleSubmit": "Add Rule",
|
||||
"rulesNoOne": "No rules. Add a rule using the form.",
|
||||
"rulesOrder": "Rules are evaluated by priority in ascending order.",
|
||||
"rulesSubmit": "Save Rules",
|
||||
"resourceErrorCreate": "Error creating resource",
|
||||
"resourceErrorCreateDescription": "An error occurred when creating the resource",
|
||||
"resourceErrorCreateMessage": "Error creating resource:",
|
||||
"resourceErrorCreateMessageDescription": "An unexpected error occurred",
|
||||
"sitesErrorFetch": "Error fetching sites",
|
||||
"sitesErrorFetchDescription": "An error occurred when fetching the sites",
|
||||
"domainsErrorFetch": "Error fetching domains",
|
||||
"domainsErrorFetchDescription": "An error occurred when fetching the domains",
|
||||
"none": "None",
|
||||
"unknown": "Unknown",
|
||||
"resources": "Resources",
|
||||
"resourcesDescription": "Resources are proxies to applications running on your private network. Create a resource for any HTTP/HTTPS or raw TCP/UDP service on your private network. Each resource must be connected to a site to enable private, secure connectivity through an encrypted WireGuard tunnel.",
|
||||
"resourcesWireGuardConnect": "Secure connectivity with WireGuard encryption",
|
||||
"resourcesMultipleAuthenticationMethods": "Configure multiple authentication methods",
|
||||
"resourcesUsersRolesAccess": "User and role-based access control",
|
||||
"resourcesErrorUpdate": "Failed to toggle resource",
|
||||
"resourcesErrorUpdateDescription": "An error occurred while updating the resource",
|
||||
"access": "Access",
|
||||
"shareLink": "{resource} Share Link",
|
||||
"resourceSelect": "Select resource",
|
||||
"shareLinks": "Share Links",
|
||||
"share": "Shareable Links",
|
||||
"shareDescription2": "Create shareable links to your resources. Links provide temporary or unlimited access to your resource. You can configure the expiration duration of the link when you create one.",
|
||||
"shareEasyCreate": "Easy to create and share",
|
||||
"shareConfigurableExpirationDuration": "Configurable expiration duration",
|
||||
"shareSecureAndRevocable": "Secure and revocable",
|
||||
"nameMin": "Name must be at least {len} characters.",
|
||||
"nameMax": "Name must not be longer than {len} characters.",
|
||||
"sitesConfirmCopy": "Please confirm that you have copied the config.",
|
||||
"unknownCommand": "Unknown command",
|
||||
"newtErrorFetchReleases": "Failed to fetch release info: {err}",
|
||||
"newtErrorFetchLatest": "Error fetching latest release: {err}",
|
||||
"newtEndpoint": "Newt Endpoint",
|
||||
"newtId": "Newt ID",
|
||||
"newtSecretKey": "Newt Secret Key",
|
||||
"architecture": "Architecture",
|
||||
"sites": "Sites",
|
||||
"siteWgAnyClients": "Use any WireGuard client to connect. You will have to address your internal resources using the peer IP.",
|
||||
"siteWgCompatibleAllClients": "Compatible with all WireGuard clients",
|
||||
"siteWgManualConfigurationRequired": "Manual configuration required",
|
||||
"userErrorNotAdminOrOwner": "User is not an admin or owner",
|
||||
"pangolinSettings": "Settings - Pangolin",
|
||||
"accessRoleYour": "Your role:",
|
||||
"accessRoleSelect2": "Select a role",
|
||||
"accessUserSelect": "Select a user",
|
||||
"otpEmailEnter": "Enter an email",
|
||||
"otpEmailEnterDescription": "Press enter to add an email after typing it in the input field.",
|
||||
"otpEmailErrorInvalid": "Invalid email address. Wildcard (*) must be the entire local part.",
|
||||
"otpEmailSmtpRequired": "SMTP Required",
|
||||
"otpEmailSmtpRequiredDescription": "SMTP must be enabled on the server to use one-time password authentication.",
|
||||
"otpEmailTitle": "One-time Passwords",
|
||||
"otpEmailTitleDescription": "Require email-based authentication for resource access",
|
||||
"otpEmailWhitelist": "Email Whitelist",
|
||||
"otpEmailWhitelistList": "Whitelisted Emails",
|
||||
"otpEmailWhitelistListDescription": "Only users with these email addresses will be able to access this resource. They will be prompted to enter a one-time password sent to their email. Wildcards (*@example.com) can be used to allow any email address from a domain.",
|
||||
"otpEmailWhitelistSave": "Save Whitelist",
|
||||
"passwordAdd": "Add Password",
|
||||
"passwordRemove": "Remove Password",
|
||||
"pincodeAdd": "Add PIN Code",
|
||||
"pincodeRemove": "Remove PIN Code",
|
||||
"resourceAuthMethods": "Authentication Methods",
|
||||
"resourceAuthMethodsDescriptions": "Allow access to the resource via additional auth methods",
|
||||
"resourceAuthSettingsSave": "Saved successfully",
|
||||
"resourceAuthSettingsSaveDescription": "Authentication settings have been saved",
|
||||
"resourceErrorAuthFetch": "Failed to fetch data",
|
||||
"resourceErrorAuthFetchDescription": "An error occurred while fetching the data",
|
||||
"resourceErrorPasswordRemove": "Error removing resource password",
|
||||
"resourceErrorPasswordRemoveDescription": "An error occurred while removing the resource password",
|
||||
"resourceErrorPasswordSetup": "Error setting resource password",
|
||||
"resourceErrorPasswordSetupDescription": "An error occurred while setting the resource password",
|
||||
"resourceErrorPincodeRemove": "Error removing resource pincode",
|
||||
"resourceErrorPincodeRemoveDescription": "An error occurred while removing the resource pincode",
|
||||
"resourceErrorPincodeSetup": "Error setting resource PIN code",
|
||||
"resourceErrorPincodeSetupDescription": "An error occurred while setting the resource PIN code",
|
||||
"resourceErrorUsersRolesSave": "Failed to set roles",
|
||||
"resourceErrorUsersRolesSaveDescription": "An error occurred while setting the roles",
|
||||
"resourceErrorWhitelistSave": "Failed to save whitelist",
|
||||
"resourceErrorWhitelistSaveDescription": "An error occurred while saving the whitelist",
|
||||
"resourcePasswordSubmit": "Enable Password Protection",
|
||||
"resourcePasswordRemove": "Resource password removed",
|
||||
"resourcePasswordRemoveDescription": "The resource password has been removed successfully",
|
||||
"resourcePasswordSetup": "Resource password set",
|
||||
"resourcePasswordSetupDescription": "The resource password has been set successfully",
|
||||
"resourcePasswordSetupTitle": "Set Password",
|
||||
"resourcePasswordSetupTitleDescription": "Set a password to protect this resource",
|
||||
"resourcePincode": "PIN Code",
|
||||
"resourcePincodeSubmit": "Enable PIN Code Protection",
|
||||
"resourcePincodeProtection": "PIN Code Protection {status}",
|
||||
"resourcePincodeRemove": "Resource pincode removed",
|
||||
"resourcePincodeRemoveDescription": "The resource password has been removed successfully",
|
||||
"resourcePincodeSetup": "Resource PIN code set",
|
||||
"resourcePincodeSetupDescription": "The resource pincode has been set successfully",
|
||||
"resourcePincodeSetupTitle": "Set Pincode",
|
||||
"resourcePincodeSetupTitleDescription": "Set a pincode to protect this resource",
|
||||
"resourceRoleDescription": "Admins can always access this resource.",
|
||||
"resourceUsersRoles": "Users & Roles",
|
||||
"resourceUsersRolesDescription": "Configure which users and roles can visit this resource",
|
||||
"resourceUsersRolesSubmit": "Save Users & Roles",
|
||||
"resourceWhitelistSave": "Saved successfully",
|
||||
"resourceWhitelistSaveDescription": "Whitelist settings have been saved",
|
||||
"ssoUse": "Use Platform SSO",
|
||||
"ssoUseDescription": "Existing users will only have to log in once for all resources that have this enabled.",
|
||||
"proxyErrorInvalidPort": "Invalid port number",
|
||||
"subdomainErrorInvalid": "Invalid subdomain",
|
||||
"domainErrorFetch": "Error fetching domains",
|
||||
"domainErrorFetchDescription": "An error occurred when fetching the domains",
|
||||
"resourceErrorUpdate": "Failed to update resource",
|
||||
"resourceErrorUpdateDescription": "An error occurred while updating the resource",
|
||||
"resourceUpdated": "Resource updated",
|
||||
"resourceUpdatedDescription": "The resource has been updated successfully",
|
||||
"resourceErrorTransfer": "Failed to transfer resource",
|
||||
"resourceErrorTransferDescription": "An error occurred while transferring the resource",
|
||||
"resourceTransferred": "Resource transferred",
|
||||
"resourceTransferredDescription": "The resource has been transferred successfully",
|
||||
"resourceErrorToggle": "Failed to toggle resource",
|
||||
"resourceErrorToggleDescription": "An error occurred while updating the resource",
|
||||
"resourceVisibilityTitle": "Visibility",
|
||||
"resourceVisibilityTitleDescription": "Completely enable or disable resource visibility",
|
||||
"resourceGeneral": "General Settings",
|
||||
"resourceGeneralDescription": "Configure the general settings for this resource",
|
||||
"resourceEnable": "Enable Resource",
|
||||
"resourceTransfer": "Transfer Resource",
|
||||
"resourceTransferDescription": "Transfer this resource to a different site",
|
||||
"resourceTransferSubmit": "Transfer Resource",
|
||||
"siteDestination": "Destination Site",
|
||||
"searchSites": "Search sites",
|
||||
"accessRoleCreate": "Create Role",
|
||||
"accessRoleCreateDescription": "Create a new role to group users and manage their permissions.",
|
||||
"accessRoleCreateSubmit": "Create Role",
|
||||
"accessRoleCreated": "Role created",
|
||||
"accessRoleCreatedDescription": "The role has been successfully created.",
|
||||
"accessRoleErrorCreate": "Failed to create role",
|
||||
"accessRoleErrorCreateDescription": "An error occurred while creating the role.",
|
||||
"accessRoleErrorNewRequired": "New role is required",
|
||||
"accessRoleErrorRemove": "Failed to remove role",
|
||||
"accessRoleErrorRemoveDescription": "An error occurred while removing the role.",
|
||||
"accessRoleName": "Role Name",
|
||||
"accessRoleQuestionRemove": "You're about to delete the <b>{name}</b> role. You cannot undo this action.",
|
||||
"accessRoleRemove": "Remove Role",
|
||||
"accessRoleRemoveDescription": "Remove a role from the organization",
|
||||
"accessRoleRemoveSubmit": "Remove Role",
|
||||
"accessRoleRemoved": "Role removed",
|
||||
"accessRoleRemovedDescription": "The role has been successfully removed.",
|
||||
"accessRoleRequiredRemove": "Before deleting this role, please select a new role to transfer existing members to.",
|
||||
"manage": "Manage",
|
||||
"sitesNotFound": "No sites found."
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
} from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Users, Globe, Database, Cog, Settings, Waypoints, Combine } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface OrgStat {
|
||||
label: string;
|
||||
|
@ -38,19 +39,21 @@ export default function OrganizationLandingCard(
|
|||
) {
|
||||
const [orgData] = useState(props);
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const orgStats: OrgStat[] = [
|
||||
{
|
||||
label: "Sites",
|
||||
label: t('sites'),
|
||||
value: orgData.overview.stats.sites,
|
||||
icon: <Combine className="h-6 w-6" />
|
||||
},
|
||||
{
|
||||
label: "Resources",
|
||||
label: t('resources'),
|
||||
value: orgData.overview.stats.resources,
|
||||
icon: <Waypoints className="h-6 w-6" />
|
||||
},
|
||||
{
|
||||
label: "Users",
|
||||
label: t('users'),
|
||||
value: orgData.overview.stats.users,
|
||||
icon: <Users className="h-6 w-6" />
|
||||
}
|
||||
|
@ -81,9 +84,9 @@ export default function OrganizationLandingCard(
|
|||
))}
|
||||
</div>
|
||||
<div className="text-center text-lg">
|
||||
Your role:{" "}
|
||||
{t('accessRoleYour')}{" "}
|
||||
<span className="font-semibold">
|
||||
{orgData.overview.isOwner ? "Owner" : orgData.overview.userRole}
|
||||
{orgData.overview.isOwner ? t('accessRoleOwner') : orgData.overview.userRole}
|
||||
</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
@ -92,7 +95,7 @@ export default function OrganizationLandingCard(
|
|||
<Link href={`/${orgData.overview.orgId}/settings`}>
|
||||
<Button size="lg" className="w-full md:w-auto">
|
||||
<Settings className="mr-2 h-4 w-4" />
|
||||
Organization Settings
|
||||
{t('orgGeneralSettings')}
|
||||
</Button>
|
||||
</Link>
|
||||
</CardFooter>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { HorizontalTabs } from "@app/components/HorizontalTabs";
|
||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface AccessPageHeaderAndNavProps {
|
||||
children: React.ReactNode;
|
||||
|
@ -12,20 +13,21 @@ export default function AccessPageHeaderAndNav({
|
|||
children,
|
||||
hasInvitations
|
||||
}: AccessPageHeaderAndNavProps) {
|
||||
const t = useTranslations();
|
||||
const navItems = [
|
||||
{
|
||||
title: "Users",
|
||||
title: t('users'),
|
||||
href: `/{orgId}/settings/access/users`
|
||||
},
|
||||
{
|
||||
title: "Roles",
|
||||
title: t('roles'),
|
||||
href: `/{orgId}/settings/access/roles`
|
||||
}
|
||||
];
|
||||
|
||||
if (hasInvitations) {
|
||||
navItems.push({
|
||||
title: "Invitations",
|
||||
title: t('invite'),
|
||||
href: `/{orgId}/settings/access/invitations`
|
||||
});
|
||||
}
|
||||
|
@ -33,8 +35,8 @@ export default function AccessPageHeaderAndNav({
|
|||
return (
|
||||
<>
|
||||
<SettingsSectionTitle
|
||||
title="Manage Users & Roles"
|
||||
description="Invite users and add them to roles to manage access to your organization"
|
||||
title={t('accessUsersRoles')}
|
||||
description={t('accessUsersRolesDescription')}
|
||||
/>
|
||||
|
||||
<HorizontalTabs items={navItems}>
|
||||
|
|
|
@ -148,7 +148,7 @@ export default function InvitationsTable({
|
|||
dialog={
|
||||
<div className="space-y-4">
|
||||
<p>
|
||||
{t('inviteQuestionRemove', {email: selectedInvitation?.email})}
|
||||
{t('inviteQuestionRemove', {email: selectedInvitation?.email || ''})}
|
||||
</p>
|
||||
<p>
|
||||
{t('inviteMessageRemove')}
|
||||
|
|
|
@ -177,7 +177,7 @@ export default function RegenerateInvitationForm({
|
|||
{!inviteLink ? (
|
||||
<div>
|
||||
<p>
|
||||
{t('inviteQuestionRegenerate', {email: invitation?.email})}
|
||||
{t('inviteQuestionRegenerate', {email: invitation?.email || ''})}
|
||||
</p>
|
||||
<div className="flex items-center space-x-2 mt-4">
|
||||
<Checkbox
|
||||
|
|
|
@ -67,7 +67,7 @@ export default async function InvitationsPage(props: InvitationsPageProps) {
|
|||
id: invite.inviteId,
|
||||
email: invite.email,
|
||||
expiresAt: new Date(Number(invite.expiresAt)).toISOString(),
|
||||
role: invite.roleName || "Unknown Role",
|
||||
role: invite.roleName || t('accessRoleUnknown'),
|
||||
roleId: invite.roleId
|
||||
};
|
||||
});
|
||||
|
|
|
@ -31,6 +31,7 @@ import { CreateRoleBody, CreateRoleResponse } from "@server/routers/role";
|
|||
import { formatAxiosError } from "@app/lib/api";
|
||||
import { createApiClient } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type CreateRoleFormProps = {
|
||||
open: boolean;
|
||||
|
@ -38,8 +39,10 @@ type CreateRoleFormProps = {
|
|||
afterCreate?: (res: CreateRoleResponse) => Promise<void>;
|
||||
};
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string({ message: "Name is required" }).max(32),
|
||||
name: z.string({ message: t('accessRoleNameRequired') }).max(32),
|
||||
description: z.string().max(255).optional()
|
||||
});
|
||||
|
||||
|
@ -76,10 +79,10 @@ export default function CreateRoleForm({
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to create role",
|
||||
title: t('accessRoleErrorCreate'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while creating the role."
|
||||
t('accessRoleErrorCreateDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -87,8 +90,8 @@ export default function CreateRoleForm({
|
|||
if (res && res.status === 201) {
|
||||
toast({
|
||||
variant: "default",
|
||||
title: "Role created",
|
||||
description: "The role has been successfully created."
|
||||
title: t('accessRoleCreated'),
|
||||
description: t('accessRoleCreatedDescription')
|
||||
});
|
||||
|
||||
if (open) {
|
||||
|
@ -115,10 +118,9 @@ export default function CreateRoleForm({
|
|||
>
|
||||
<CredenzaContent>
|
||||
<CredenzaHeader>
|
||||
<CredenzaTitle>Create Role</CredenzaTitle>
|
||||
<CredenzaTitle>{t('accessRoleCreate')}</CredenzaTitle>
|
||||
<CredenzaDescription>
|
||||
Create a new role to group users and manage their
|
||||
permissions.
|
||||
{t('accessRoleCreateDescription')}
|
||||
</CredenzaDescription>
|
||||
</CredenzaHeader>
|
||||
<CredenzaBody>
|
||||
|
@ -133,7 +135,7 @@ export default function CreateRoleForm({
|
|||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Role Name</FormLabel>
|
||||
<FormLabel>{t('accessRoleName')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
|
@ -146,7 +148,7 @@ export default function CreateRoleForm({
|
|||
name="description"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Description</FormLabel>
|
||||
<FormLabel>{t('description')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
|
@ -159,7 +161,7 @@ export default function CreateRoleForm({
|
|||
</CredenzaBody>
|
||||
<CredenzaFooter>
|
||||
<CredenzaClose asChild>
|
||||
<Button variant="outline">Close</Button>
|
||||
<Button variant="outline">{t('close')}</Button>
|
||||
</CredenzaClose>
|
||||
<Button
|
||||
type="submit"
|
||||
|
@ -167,7 +169,7 @@ export default function CreateRoleForm({
|
|||
loading={loading}
|
||||
disabled={loading}
|
||||
>
|
||||
Create Role
|
||||
{t('accessRoleCreateSubmit')}
|
||||
</Button>
|
||||
</CredenzaFooter>
|
||||
</CredenzaContent>
|
||||
|
|
|
@ -38,6 +38,7 @@ import { RoleRow } from "./RolesTable";
|
|||
import { formatAxiosError } from "@app/lib/api";
|
||||
import { createApiClient } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type CreateRoleFormProps = {
|
||||
open: boolean;
|
||||
|
@ -46,8 +47,10 @@ type CreateRoleFormProps = {
|
|||
afterDelete?: () => void;
|
||||
};
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const formSchema = z.object({
|
||||
newRoleId: z.string({ message: "New role is required" })
|
||||
newRoleId: z.string({ message: t('accessRoleErrorNewRequired') })
|
||||
});
|
||||
|
||||
export default function DeleteRoleForm({
|
||||
|
@ -73,10 +76,10 @@ export default function DeleteRoleForm({
|
|||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to fetch roles",
|
||||
title: t('accessRoleErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while fetching the roles"
|
||||
t('accessRoleErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -112,10 +115,10 @@ export default function DeleteRoleForm({
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to remove role",
|
||||
title: t('accessRoleErrorRemove'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while removing the role."
|
||||
t('accessRoleErrorRemoveDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -123,8 +126,8 @@ export default function DeleteRoleForm({
|
|||
if (res && res.status === 200) {
|
||||
toast({
|
||||
variant: "default",
|
||||
title: "Role removed",
|
||||
description: "The role has been successfully removed."
|
||||
title: t('accessRoleRemoved'),
|
||||
description: t('accessRoleRemovedDescription')
|
||||
});
|
||||
|
||||
if (open) {
|
||||
|
@ -151,22 +154,19 @@ export default function DeleteRoleForm({
|
|||
>
|
||||
<CredenzaContent>
|
||||
<CredenzaHeader>
|
||||
<CredenzaTitle>Remove Role</CredenzaTitle>
|
||||
<CredenzaTitle>{t('accessRoleRemove')}</CredenzaTitle>
|
||||
<CredenzaDescription>
|
||||
Remove a role from the organization
|
||||
{t('accessRoleRemoveDescription')}
|
||||
</CredenzaDescription>
|
||||
</CredenzaHeader>
|
||||
<CredenzaBody>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-4">
|
||||
<p>
|
||||
You're about to delete the{" "}
|
||||
<b>{roleToDelete.name}</b> role. You cannot
|
||||
undo this action.
|
||||
{t('accessRoleQuestionRemove', {name: roleToDelete.name})}
|
||||
</p>
|
||||
<p>
|
||||
Before deleting this role, please select a
|
||||
new role to transfer existing members to.
|
||||
{t('accessRoleRequiredRemove')}
|
||||
</p>
|
||||
</div>
|
||||
<Form {...form}>
|
||||
|
@ -180,7 +180,7 @@ export default function DeleteRoleForm({
|
|||
name="newRoleId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Role</FormLabel>
|
||||
<FormLabel>{t('role')}</FormLabel>
|
||||
<Select
|
||||
onValueChange={
|
||||
field.onChange
|
||||
|
@ -189,7 +189,7 @@ export default function DeleteRoleForm({
|
|||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select role" />
|
||||
<SelectValue placeholder={t('accessRoleSelect')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
|
@ -215,7 +215,7 @@ export default function DeleteRoleForm({
|
|||
</CredenzaBody>
|
||||
<CredenzaFooter>
|
||||
<CredenzaClose asChild>
|
||||
<Button variant="outline">Close</Button>
|
||||
<Button variant="outline">{t('close')}</Button>
|
||||
</CredenzaClose>
|
||||
<Button
|
||||
type="submit"
|
||||
|
@ -223,7 +223,7 @@ export default function DeleteRoleForm({
|
|||
loading={loading}
|
||||
disabled={loading}
|
||||
>
|
||||
Remove Role
|
||||
{t('accessRoleRemoveSubmit')}
|
||||
</Button>
|
||||
</CredenzaFooter>
|
||||
</CredenzaContent>
|
||||
|
|
|
@ -24,7 +24,7 @@ export function UsersDataTable<TData, TValue>({
|
|||
<DataTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
title="Users"
|
||||
title={t('users')}
|
||||
searchPlaceholder={t('accessUsersSearch')}
|
||||
searchColumn="email"
|
||||
onAdd={inviteUser}
|
||||
|
|
|
@ -181,7 +181,7 @@ export default function UsersTable({ users: u }: UsersTableProps) {
|
|||
variant="ghost"
|
||||
className="opacity-0 cursor-default"
|
||||
>
|
||||
Placeholder
|
||||
{t('placeholder')}
|
||||
</Button>
|
||||
)}
|
||||
{!userRow.isOwner && (
|
||||
|
@ -192,7 +192,7 @@ export default function UsersTable({ users: u }: UsersTableProps) {
|
|||
variant={"outlinePrimary"}
|
||||
className="ml-2"
|
||||
>
|
||||
Manage
|
||||
{t('manage')}
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</Button>
|
||||
</Link>
|
||||
|
@ -210,10 +210,10 @@ export default function UsersTable({ users: u }: UsersTableProps) {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to remove user",
|
||||
title: t('userErrorOrgRemove'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while removing the user."
|
||||
t('userErrorOrgRemoveDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -221,8 +221,8 @@ export default function UsersTable({ users: u }: UsersTableProps) {
|
|||
if (res && res.status === 200) {
|
||||
toast({
|
||||
variant: "default",
|
||||
title: "User removed",
|
||||
description: `The user ${selectedUser.email} has been removed from the organization.`
|
||||
title: t('userOrgRemoved'),
|
||||
description: t('userOrgRemovedDescription', {email: selectedUser.email || ''})
|
||||
});
|
||||
|
||||
setUsers((prev) =>
|
||||
|
@ -244,29 +244,19 @@ export default function UsersTable({ users: u }: UsersTableProps) {
|
|||
dialog={
|
||||
<div className="space-y-4">
|
||||
<p>
|
||||
Are you sure you want to remove{" "}
|
||||
<b>
|
||||
{selectedUser?.email ||
|
||||
selectedUser?.name ||
|
||||
selectedUser?.username}
|
||||
</b>{" "}
|
||||
from the organization?
|
||||
{t('userQuestionOrgRemove', {email: selectedUser?.email || selectedUser?.name || selectedUser?.username || ''})}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Once removed, this user will no longer have access
|
||||
to the organization. You can always re-invite them
|
||||
later, but they will need to accept the invitation
|
||||
again.
|
||||
{t('userMessageOrgRemove')}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To confirm, please type the name of the of the user
|
||||
below.
|
||||
{t('userMessageOrgConfirm')}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
buttonText="Confirm Remove User"
|
||||
buttonText={t('userRemoveOrgConfirm')}
|
||||
onConfirm={removeUser}
|
||||
string={
|
||||
selectedUser?.email ||
|
||||
|
@ -274,7 +264,7 @@ export default function UsersTable({ users: u }: UsersTableProps) {
|
|||
selectedUser?.username ||
|
||||
""
|
||||
}
|
||||
title="Remove User from Organization"
|
||||
title={t('userRemoveOrg')}
|
||||
/>
|
||||
|
||||
<UsersDataTable
|
||||
|
|
|
@ -40,6 +40,7 @@ import {
|
|||
import { formatAxiosError } from "@app/lib/api";
|
||||
import { createApiClient } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const formSchema = z.object({
|
||||
username: z.string(),
|
||||
|
@ -64,6 +65,8 @@ export default function AccessControlsPage() {
|
|||
}
|
||||
});
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchRoles() {
|
||||
const res = await api
|
||||
|
@ -72,10 +75,10 @@ export default function AccessControlsPage() {
|
|||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to fetch roles",
|
||||
title: t('accessRoleErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while fetching the roles"
|
||||
t('accessRoleErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -100,10 +103,10 @@ export default function AccessControlsPage() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to add user to role",
|
||||
title: t('accessRoleErrorAdd'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while adding user to the role."
|
||||
t('accessRoleErrorAddDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -111,8 +114,8 @@ export default function AccessControlsPage() {
|
|||
if (res && res.status === 200) {
|
||||
toast({
|
||||
variant: "default",
|
||||
title: "User saved",
|
||||
description: "The user has been updated."
|
||||
title: t('userSaved'),
|
||||
description: t('userSavedDescription')
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -123,10 +126,9 @@ export default function AccessControlsPage() {
|
|||
<SettingsContainer>
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>Access Controls</SettingsSectionTitle>
|
||||
<SettingsSectionTitle>{t('accessControls')}</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Manage what this user can access and do in the
|
||||
organization
|
||||
{t('accessControlsDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
|
||||
|
@ -143,14 +145,14 @@ export default function AccessControlsPage() {
|
|||
name="roleId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Role</FormLabel>
|
||||
<FormLabel>{t('role')}</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select role" />
|
||||
<SelectValue placeholder={t('accessRoleSelect')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
|
@ -180,7 +182,7 @@ export default function AccessControlsPage() {
|
|||
disabled={loading}
|
||||
form="access-controls-form"
|
||||
>
|
||||
Save Access Controls
|
||||
{t('accessControlsSubmit')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
import Link from "next/link";
|
||||
import { cache } from "react";
|
||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface UserLayoutProps {
|
||||
children: React.ReactNode;
|
||||
|
@ -26,6 +27,8 @@ export default async function UserLayoutProps(props: UserLayoutProps) {
|
|||
|
||||
const { children } = props;
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
let user = null;
|
||||
try {
|
||||
const getOrgUser = cache(async () =>
|
||||
|
@ -42,7 +45,7 @@ export default async function UserLayoutProps(props: UserLayoutProps) {
|
|||
|
||||
const navItems = [
|
||||
{
|
||||
title: "Access Controls",
|
||||
title: t('accessControls'),
|
||||
href: "/{orgId}/settings/access/users/{userId}/access-controls"
|
||||
}
|
||||
];
|
||||
|
@ -51,7 +54,7 @@ export default async function UserLayoutProps(props: UserLayoutProps) {
|
|||
<>
|
||||
<SettingsSectionTitle
|
||||
title={`${user?.email}`}
|
||||
description="Manage the settings on this user"
|
||||
description={t('userDescription2')}
|
||||
/>
|
||||
<OrgUserProvider orgUser={user}>
|
||||
<HorizontalTabs items={navItems}>
|
||||
|
|
|
@ -44,6 +44,7 @@ import { formatAxiosError } from "@app/lib/api";
|
|||
import { createApiClient } from "@app/lib/api";
|
||||
import { Checkbox } from "@app/components/ui/checkbox";
|
||||
import { ListIdpsResponse } from "@server/routers/idp";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type UserType = "internal" | "oidc";
|
||||
|
||||
|
@ -59,28 +60,30 @@ interface IdpOption {
|
|||
type: string;
|
||||
}
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const internalFormSchema = z.object({
|
||||
email: z.string().email({ message: "Invalid email address" }),
|
||||
validForHours: z.string().min(1, { message: "Please select a duration" }),
|
||||
roleId: z.string().min(1, { message: "Please select a role" })
|
||||
email: z.string().email({ message: t('emailInvalid') }),
|
||||
validForHours: z.string().min(1, { message: t('inviteValidityDuration') }),
|
||||
roleId: z.string().min(1, { message: t('accessRoleSelectPlease') })
|
||||
});
|
||||
|
||||
const externalFormSchema = z.object({
|
||||
username: z.string().min(1, { message: "Username is required" }),
|
||||
username: z.string().min(1, { message: t('usernameRequired') }),
|
||||
email: z
|
||||
.string()
|
||||
.email({ message: "Invalid email address" })
|
||||
.email({ message: t('emailInvalid') })
|
||||
.optional()
|
||||
.or(z.literal("")),
|
||||
name: z.string().optional(),
|
||||
roleId: z.string().min(1, { message: "Please select a role" }),
|
||||
idpId: z.string().min(1, { message: "Please select an identity provider" })
|
||||
roleId: z.string().min(1, { message: t('accessRoleSelectPlease') }),
|
||||
idpId: z.string().min(1, { message: t('idpSelectPlease') })
|
||||
});
|
||||
|
||||
const formatIdpType = (type: string) => {
|
||||
switch (type.toLowerCase()) {
|
||||
case "oidc":
|
||||
return "Generic OAuth2/OIDC provider.";
|
||||
return t('idpGenericOidc');
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
|
@ -103,13 +106,13 @@ export default function Page() {
|
|||
const [dataLoaded, setDataLoaded] = useState(false);
|
||||
|
||||
const validFor = [
|
||||
{ hours: 24, name: "1 day" },
|
||||
{ hours: 48, name: "2 days" },
|
||||
{ hours: 72, name: "3 days" },
|
||||
{ hours: 96, name: "4 days" },
|
||||
{ hours: 120, name: "5 days" },
|
||||
{ hours: 144, name: "6 days" },
|
||||
{ hours: 168, name: "7 days" }
|
||||
{ hours: 24, name: t('day', {count: 1}) },
|
||||
{ hours: 48, name: t('day', {count: 2}) },
|
||||
{ hours: 72, name: t('day', {count: 3}) },
|
||||
{ hours: 96, name: t('day', {count: 4}) },
|
||||
{ hours: 120, name: t('day', {count: 5}) },
|
||||
{ hours: 144, name: t('day', {count: 6}) },
|
||||
{ hours: 168, name: t('day', {count: 7}) }
|
||||
];
|
||||
|
||||
const internalForm = useForm<z.infer<typeof internalFormSchema>>({
|
||||
|
@ -155,10 +158,10 @@ export default function Page() {
|
|||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to fetch roles",
|
||||
title: t('accessRoleErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while fetching the roles"
|
||||
t('accessRoleErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -178,10 +181,10 @@ export default function Page() {
|
|||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to fetch identity providers",
|
||||
title: t('idpErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while fetching identity providers"
|
||||
t('idpErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -218,17 +221,16 @@ export default function Page() {
|
|||
if (e.response?.status === 409) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "User Already Exists",
|
||||
description:
|
||||
"This user is already a member of the organization."
|
||||
title: t('userErrorExists'),
|
||||
description: t('userErrorExistsDescription')
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to invite user",
|
||||
title: t('inviteError'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while inviting the user"
|
||||
t('inviteErrorDescription')
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -238,8 +240,8 @@ export default function Page() {
|
|||
setInviteLink(res.data.data.inviteLink);
|
||||
toast({
|
||||
variant: "default",
|
||||
title: "User invited",
|
||||
description: "The user has been successfully invited."
|
||||
title: t('userInvited'),
|
||||
description: t('userInvitedDescription')
|
||||
});
|
||||
|
||||
setExpiresInDays(parseInt(values.validForHours) / 24);
|
||||
|
@ -265,10 +267,10 @@ export default function Page() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to create user",
|
||||
title: t('userErrorCreate'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while creating the user"
|
||||
t('userErrorCreateDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -276,8 +278,8 @@ export default function Page() {
|
|||
if (res && res.status === 201) {
|
||||
toast({
|
||||
variant: "default",
|
||||
title: "User created",
|
||||
description: "The user has been successfully created."
|
||||
title: t('userCreated'),
|
||||
description: t('userCreatedDescription')
|
||||
});
|
||||
router.push(`/${orgId}/settings/access/users`);
|
||||
}
|
||||
|
@ -288,13 +290,13 @@ export default function Page() {
|
|||
const userTypes: ReadonlyArray<UserTypeOption> = [
|
||||
{
|
||||
id: "internal",
|
||||
title: "Internal User",
|
||||
description: "Invite a user to join your organization directly."
|
||||
title: t('userTypeInternal'),
|
||||
description: t('userTypeInternalDescription')
|
||||
},
|
||||
{
|
||||
id: "oidc",
|
||||
title: "External User",
|
||||
description: "Create a user with an external identity provider."
|
||||
title: t('userTypeExternal'),
|
||||
description: t('userTypeExternalDescription')
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -302,8 +304,8 @@ export default function Page() {
|
|||
<>
|
||||
<div className="flex justify-between">
|
||||
<HeaderTitle
|
||||
title="Create User"
|
||||
description="Follow the steps below to create a new user"
|
||||
title={t('accessUserCreate')}
|
||||
description={t('accessUserCreateDescription')}
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
|
@ -311,7 +313,7 @@ export default function Page() {
|
|||
router.push(`/${orgId}/settings/access/users`);
|
||||
}}
|
||||
>
|
||||
See All Users
|
||||
{t('userSeeAll')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
@ -320,10 +322,10 @@ export default function Page() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
User Type
|
||||
{t('userTypeTitle')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Determine how you want to create the user
|
||||
{t('userTypeDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -349,10 +351,10 @@ export default function Page() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
User Information
|
||||
{t('userInfo')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Enter the details for the new user
|
||||
{t('userSettingsDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -373,7 +375,7 @@ export default function Page() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Email
|
||||
{t('email')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
|
@ -402,8 +404,7 @@ export default function Page() {
|
|||
htmlFor="send-email"
|
||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Send invite email to
|
||||
user
|
||||
{t('inviteEmailSent')}
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
|
@ -416,7 +417,7 @@ export default function Page() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Valid For
|
||||
{t('inviteValid')}
|
||||
</FormLabel>
|
||||
<Select
|
||||
onValueChange={
|
||||
|
@ -428,7 +429,7 @@ export default function Page() {
|
|||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select duration" />
|
||||
<SelectValue placeholder={t('selectDuration')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
|
@ -463,7 +464,7 @@ export default function Page() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Role
|
||||
{t('role')}
|
||||
</FormLabel>
|
||||
<Select
|
||||
onValueChange={
|
||||
|
@ -472,7 +473,7 @@ export default function Page() {
|
|||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select role" />
|
||||
<SelectValue placeholder={t('accessRoleSelect')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
|
@ -503,37 +504,16 @@ export default function Page() {
|
|||
<div className="max-w-md space-y-4">
|
||||
{sendEmail && (
|
||||
<p>
|
||||
An email has
|
||||
been sent to the
|
||||
user with the
|
||||
access link
|
||||
below. They must
|
||||
access the link
|
||||
to accept the
|
||||
invitation.
|
||||
{t('inviteEmailSentDescription')}
|
||||
</p>
|
||||
)}
|
||||
{!sendEmail && (
|
||||
<p>
|
||||
The user has
|
||||
been invited.
|
||||
They must access
|
||||
the link below
|
||||
to accept the
|
||||
invitation.
|
||||
{t('inviteSentDescription')}
|
||||
</p>
|
||||
)}
|
||||
<p>
|
||||
The invite will
|
||||
expire in{" "}
|
||||
<b>
|
||||
{expiresInDays}{" "}
|
||||
{expiresInDays ===
|
||||
1
|
||||
? "day"
|
||||
: "days"}
|
||||
</b>
|
||||
.
|
||||
{t('inviteExpiresIn', {days: expiresInDays})}
|
||||
</p>
|
||||
<CopyTextBox
|
||||
text={inviteLink}
|
||||
|
@ -554,20 +534,16 @@ export default function Page() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
Identity Provider
|
||||
{t('idpTitle')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Select the identity provider for the
|
||||
external user
|
||||
{t('idpSelect')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
{idps.length === 0 ? (
|
||||
<p className="text-muted-foreground">
|
||||
No identity providers are
|
||||
configured. Please configure an
|
||||
identity provider before creating
|
||||
external users.
|
||||
{t('idpNotConfigured')}
|
||||
</p>
|
||||
) : (
|
||||
<Form {...externalForm}>
|
||||
|
@ -621,10 +597,10 @@ export default function Page() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
User Information
|
||||
{t('userSettings')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Enter the details for the new user
|
||||
{t('userSettingsDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -645,7 +621,7 @@ export default function Page() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Username
|
||||
{t('username')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
|
@ -653,15 +629,7 @@ export default function Page() {
|
|||
/>
|
||||
</FormControl>
|
||||
<p className="text-sm text-muted-foreground mt-1">
|
||||
This must
|
||||
match the
|
||||
unique
|
||||
username
|
||||
that exists
|
||||
in the
|
||||
selected
|
||||
identity
|
||||
provider.
|
||||
{t('usernameUniq')}
|
||||
</p>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
@ -676,8 +644,7 @@ export default function Page() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Email
|
||||
(Optional)
|
||||
{t('emailOptional')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
|
@ -697,8 +664,7 @@ export default function Page() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Name
|
||||
(Optional)
|
||||
{t('nameOptional')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
|
@ -718,7 +684,7 @@ export default function Page() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Role
|
||||
{t('role')}
|
||||
</FormLabel>
|
||||
<Select
|
||||
onValueChange={
|
||||
|
@ -727,7 +693,7 @@ export default function Page() {
|
|||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select role" />
|
||||
<SelectValue placeholder={t('accessRoleSelect')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
|
@ -771,7 +737,7 @@ export default function Page() {
|
|||
router.push(`/${orgId}/settings/access/users`);
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
{userType && dataLoaded && (
|
||||
<Button
|
||||
|
@ -783,7 +749,7 @@ export default function Page() {
|
|||
(userType === "internal" && inviteLink !== null)
|
||||
}
|
||||
>
|
||||
Create User
|
||||
{t('accessUserCreate')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -11,6 +11,7 @@ import { verifySession } from "@app/lib/auth/verifySession";
|
|||
import AccessPageHeaderAndNav from "../AccessPageHeaderAndNav";
|
||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type UsersPageProps = {
|
||||
params: Promise<{ orgId: string }>;
|
||||
|
@ -24,6 +25,8 @@ export default async function UsersPage(props: UsersPageProps) {
|
|||
const getUser = cache(verifySession);
|
||||
const user = await getUser();
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
let users: ListUsersResponse["users"] = [];
|
||||
let hasInvitations = false;
|
||||
|
||||
|
@ -77,15 +80,13 @@ export default async function UsersPage(props: UsersPageProps) {
|
|||
email: user.email,
|
||||
type: user.type,
|
||||
idpId: user.idpId,
|
||||
idpName: user.idpName || "Internal",
|
||||
status: "Confirmed",
|
||||
role: user.isOwner ? "Owner" : user.roleName || "Member",
|
||||
idpName: user.idpName || t('idpNameInternal'),
|
||||
status: t('userConfirmed'),
|
||||
role: user.isOwner ? t('accessRoleOwner') : user.roleName || t('accessRoleMember'),
|
||||
isOwner: user.isOwner || false
|
||||
};
|
||||
});
|
||||
|
||||
const t = await getTranslations();
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsSectionTitle
|
||||
|
|
|
@ -121,7 +121,7 @@ export default function OrgApiKeysTable({
|
|||
},
|
||||
{
|
||||
accessorKey: "key",
|
||||
header: "Key",
|
||||
header: t('key'),
|
||||
cell: ({ row }) => {
|
||||
const r = row.original;
|
||||
return <span className="font-mono">{r.key}</span>;
|
||||
|
@ -129,7 +129,7 @@ export default function OrgApiKeysTable({
|
|||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Created At",
|
||||
header: t('createdAt'),
|
||||
cell: ({ row }) => {
|
||||
const r = row.original;
|
||||
return <span>{moment(r.createdAt).format("lll")} </span>;
|
||||
|
|
|
@ -45,10 +45,10 @@ export default function Page() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('apiKeysPermissionsErrorLoadingActions'),
|
||||
title: "Error loading API key actions",
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
t('apiKeysPermissionsErrorLoadingActions')
|
||||
"Error loading API key actions"
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -79,18 +79,18 @@ export default function Page() {
|
|||
)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(t('apiKeysPermissionsErrorUpdate'), e);
|
||||
console.error("Error setting permissions", e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('apiKeysPermissionsErrorUpdate'),
|
||||
title: "Error setting permissions",
|
||||
description: formatAxiosError(e)
|
||||
});
|
||||
});
|
||||
|
||||
if (actionsRes && actionsRes.status === 200) {
|
||||
toast({
|
||||
title: t('apiKeysPermissionsUpdated'),
|
||||
description: t('apiKeysPermissionsUpdatedDescription')
|
||||
title: "Permissions updated",
|
||||
description: "The permissions have been updated."
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -58,16 +58,14 @@ import CopyTextBox from "@app/components/CopyTextBox";
|
|||
import PermissionsSelectBox from "@app/components/PermissionsSelectBox";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const createFormSchema = z.object({
|
||||
name: z
|
||||
.string()
|
||||
.min(2, {
|
||||
message: t('apiKeysNameMin')
|
||||
message: "Name must be at least 2 characters."
|
||||
})
|
||||
.max(255, {
|
||||
message: t('apiKeysNameMax')
|
||||
message: "Name must not be longer than 255 characters."
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -82,7 +80,7 @@ const copiedFormSchema = z
|
|||
return data.copied;
|
||||
},
|
||||
{
|
||||
message: t('apiKeysConfirmCopy2'),
|
||||
message: "You must confirm that you have copied the API key.",
|
||||
path: ["copied"]
|
||||
}
|
||||
);
|
||||
|
@ -116,6 +114,8 @@ export default function Page() {
|
|||
}
|
||||
});
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
async function onSubmit(data: CreateFormValues) {
|
||||
setCreateLoading(true);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import UserProvider from "@app/providers/UserProvider";
|
|||
import { Layout } from "@app/components/Layout";
|
||||
import { SidebarNavItem, SidebarNavProps } from "@app/components/SidebarNav";
|
||||
import { orgNavItems } from "@app/app/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
|
@ -46,6 +47,8 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
|
|||
|
||||
const cookie = await authCookieHeader();
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
try {
|
||||
const getOrgUser = cache(() =>
|
||||
internal.get<AxiosResponse<GetOrgUserResponse>>(
|
||||
|
@ -56,7 +59,7 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
|
|||
const orgUser = await getOrgUser();
|
||||
|
||||
if (!orgUser.data.data.isAdmin && !orgUser.data.data.isOwner) {
|
||||
throw new Error("User is not an admin or owner");
|
||||
throw new Error(t('userErrorNotAdminOrOwner'));
|
||||
}
|
||||
} catch {
|
||||
redirect(`/${params.orgId}`);
|
||||
|
|
|
@ -22,7 +22,7 @@ export function ResourcesDataTable<TData, TValue>({
|
|||
<DataTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
title="Resources"
|
||||
title={t('resources')}
|
||||
searchPlaceholder={t('resourcesSearch')}
|
||||
searchColumn="name"
|
||||
onAdd={createResource}
|
||||
|
|
|
@ -4,6 +4,7 @@ import React, { useState, useEffect } from "react";
|
|||
import { Server, Lock, Key, Users, X, ArrowRight } from "lucide-react"; // Replace with actual imports
|
||||
import { Card, CardContent } from "@app/components/ui/card";
|
||||
import { Button } from "@app/components/ui/button";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export const ResourcesSplashCard = () => {
|
||||
const [isDismissed, setIsDismissed] = useState(false);
|
||||
|
@ -22,6 +23,8 @@ export const ResourcesSplashCard = () => {
|
|||
localStorage.setItem(key, "true");
|
||||
};
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
if (isDismissed) {
|
||||
return null;
|
||||
}
|
||||
|
@ -31,7 +34,7 @@ export const ResourcesSplashCard = () => {
|
|||
<button
|
||||
onClick={handleDismiss}
|
||||
className="absolute top-2 right-2 p-2"
|
||||
aria-label="Dismiss"
|
||||
aria-label={t('dismiss')}
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
|
@ -39,24 +42,23 @@ export const ResourcesSplashCard = () => {
|
|||
<div className="space-y-4">
|
||||
<h3 className="text-xl font-semibold flex items-center gap-2">
|
||||
<Server className="text-blue-500" />
|
||||
Resources
|
||||
{t('resources')}
|
||||
</h3>
|
||||
<p className="text-sm">
|
||||
Resources are proxies to applications running on your private network. Create a resource for any HTTP/HTTPS or raw TCP/UDP service on your private network.
|
||||
Each resource must be connected to a site to enable private, secure connectivity through an encrypted WireGuard tunnel.
|
||||
{t('resourcesDescription')}
|
||||
</p>
|
||||
<ul className="text-sm text-muted-foreground space-y-2">
|
||||
<li className="flex items-center gap-2">
|
||||
<Lock className="text-green-500 w-4 h-4" />
|
||||
Secure connectivity with WireGuard encryption
|
||||
{t('resourcesWireGuardConnect')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<Key className="text-yellow-500 w-4 h-4" />
|
||||
Configure multiple authentication methods
|
||||
{t('resourcesMultipleAuthenticationMethods')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<Users className="text-purple-500 w-4 h-4" />
|
||||
User and role-based access control
|
||||
{t('resourcesUsersRolesAccess')}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -183,7 +183,7 @@ export default function SitesTable({ resources, orgId }: ResourcesTableProps) {
|
|||
},
|
||||
{
|
||||
accessorKey: "protocol",
|
||||
header: "Protocol",
|
||||
header: t('protocol'),
|
||||
cell: ({ row }) => {
|
||||
const resourceRow = row.original;
|
||||
return <span>{resourceRow.protocol.toUpperCase()}</span>;
|
||||
|
@ -191,7 +191,7 @@ export default function SitesTable({ resources, orgId }: ResourcesTableProps) {
|
|||
},
|
||||
{
|
||||
accessorKey: "domain",
|
||||
header: "Access",
|
||||
header: t('access'),
|
||||
cell: ({ row }) => {
|
||||
const resourceRow = row.original;
|
||||
return (
|
||||
|
@ -249,7 +249,7 @@ export default function SitesTable({ resources, orgId }: ResourcesTableProps) {
|
|||
},
|
||||
{
|
||||
accessorKey: "enabled",
|
||||
header: "Enabled",
|
||||
header: t('enabled'),
|
||||
cell: ({ row }) => (
|
||||
<Switch
|
||||
defaultChecked={row.original.enabled}
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue
|
||||
} from "@/components/ui/select";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface DomainOption {
|
||||
baseDomain: string;
|
||||
|
@ -23,10 +24,12 @@ interface CustomDomainInputProps {
|
|||
onChange?: (value: string, selectedDomainId: string) => void;
|
||||
}
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
export default function CustomDomainInput({
|
||||
domainOptions,
|
||||
selectedDomainId,
|
||||
placeholder = "Subdomain",
|
||||
placeholder = t('subdomain'),
|
||||
value: defaultValue,
|
||||
onChange
|
||||
}: CustomDomainInputProps) {
|
||||
|
|
|
@ -31,6 +31,7 @@ import { AxiosResponse } from "axios";
|
|||
import { Resource } from "@server/db/schemas";
|
||||
import { createApiClient } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const setPasswordFormSchema = z.object({
|
||||
password: z.string().min(4).max(100)
|
||||
|
@ -64,6 +65,8 @@ export default function SetResourcePasswordForm({
|
|||
defaultValues
|
||||
});
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
return;
|
||||
|
@ -81,18 +84,17 @@ export default function SetResourcePasswordForm({
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error setting resource password",
|
||||
title: t('resourceErrorPasswordSetup'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while setting the resource password"
|
||||
t('resourceErrorPasswordSetupDescription')
|
||||
)
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
toast({
|
||||
title: "Resource password set",
|
||||
description:
|
||||
"The resource password has been set successfully"
|
||||
title: t('resourcePasswordSetup'),
|
||||
description: t('resourcePasswordSetupDescription')
|
||||
});
|
||||
|
||||
if (onSetPassword) {
|
||||
|
@ -114,9 +116,9 @@ export default function SetResourcePasswordForm({
|
|||
>
|
||||
<CredenzaContent>
|
||||
<CredenzaHeader>
|
||||
<CredenzaTitle>Set Password</CredenzaTitle>
|
||||
<CredenzaTitle>{t('resourcePasswordSetupTitle')}</CredenzaTitle>
|
||||
<CredenzaDescription>
|
||||
Set a password to protect this resource
|
||||
{t('resourcePasswordSetupTitleDescription')}
|
||||
</CredenzaDescription>
|
||||
</CredenzaHeader>
|
||||
<CredenzaBody>
|
||||
|
@ -131,7 +133,7 @@ export default function SetResourcePasswordForm({
|
|||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormLabel>{t('password')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
autoComplete="off"
|
||||
|
@ -148,7 +150,7 @@ export default function SetResourcePasswordForm({
|
|||
</CredenzaBody>
|
||||
<CredenzaFooter>
|
||||
<CredenzaClose asChild>
|
||||
<Button variant="outline">Close</Button>
|
||||
<Button variant="outline">{t('close')}</Button>
|
||||
</CredenzaClose>
|
||||
<Button
|
||||
type="submit"
|
||||
|
@ -156,7 +158,7 @@ export default function SetResourcePasswordForm({
|
|||
loading={loading}
|
||||
disabled={loading}
|
||||
>
|
||||
Enable Password Protection
|
||||
{t('resourcePasswordSubmit')}
|
||||
</Button>
|
||||
</CredenzaFooter>
|
||||
</CredenzaContent>
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
} from "@app/components/ui/input-otp";
|
||||
import { createApiClient } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const setPincodeFormSchema = z.object({
|
||||
pincode: z.string().length(6)
|
||||
|
@ -69,6 +70,8 @@ export default function SetResourcePincodeForm({
|
|||
defaultValues
|
||||
});
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
return;
|
||||
|
@ -86,18 +89,17 @@ export default function SetResourcePincodeForm({
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error setting resource PIN code",
|
||||
title: t('resourceErrorPincodeSetup'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while setting the resource PIN code"
|
||||
t('resourceErrorPincodeSetupDescription')
|
||||
)
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
toast({
|
||||
title: "Resource PIN code set",
|
||||
description:
|
||||
"The resource pincode has been set successfully"
|
||||
title: t('resourcePincodeSetup'),
|
||||
description: t('resourcePincodeSetupDescription')
|
||||
});
|
||||
|
||||
if (onSetPincode) {
|
||||
|
@ -119,9 +121,9 @@ export default function SetResourcePincodeForm({
|
|||
>
|
||||
<CredenzaContent>
|
||||
<CredenzaHeader>
|
||||
<CredenzaTitle>Set Pincode</CredenzaTitle>
|
||||
<CredenzaTitle>{t('resourcePincodeSetupTitle')}</CredenzaTitle>
|
||||
<CredenzaDescription>
|
||||
Set a pincode to protect this resource
|
||||
{t('resourcePincodeSetupTitleDescription')}
|
||||
</CredenzaDescription>
|
||||
</CredenzaHeader>
|
||||
<CredenzaBody>
|
||||
|
@ -136,7 +138,7 @@ export default function SetResourcePincodeForm({
|
|||
name="pincode"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>PIN Code</FormLabel>
|
||||
<FormLabel>{t('resourcePincode')}</FormLabel>
|
||||
<FormControl>
|
||||
<div className="flex justify-center">
|
||||
<InputOTP
|
||||
|
@ -182,7 +184,7 @@ export default function SetResourcePincodeForm({
|
|||
</CredenzaBody>
|
||||
<CredenzaFooter>
|
||||
<CredenzaClose asChild>
|
||||
<Button variant="outline">Close</Button>
|
||||
<Button variant="outline">{t('close')}</Button>
|
||||
</CredenzaClose>
|
||||
<Button
|
||||
type="submit"
|
||||
|
@ -190,7 +192,7 @@ export default function SetResourcePincodeForm({
|
|||
loading={loading}
|
||||
disabled={loading}
|
||||
>
|
||||
Enable PIN Code Protection
|
||||
{t('resourcePincodeSubmit')}
|
||||
</Button>
|
||||
</CredenzaFooter>
|
||||
</CredenzaContent>
|
||||
|
|
|
@ -48,6 +48,7 @@ import { useRouter } from "next/navigation";
|
|||
import { UserType } from "@server/types/UserTypes";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
||||
import { InfoIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const UsersRolesFormSchema = z.object({
|
||||
roles: z.array(
|
||||
|
@ -129,6 +130,8 @@ export default function ResourceAuthenticationPage() {
|
|||
defaultValues: { emails: [] }
|
||||
});
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
|
@ -203,10 +206,10 @@ export default function ResourceAuthenticationPage() {
|
|||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to fetch data",
|
||||
title: t('resourceErrorAuthFetch'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while fetching the data"
|
||||
t('resourceErrorAuthFetchDescription')
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -233,18 +236,18 @@ export default function ResourceAuthenticationPage() {
|
|||
});
|
||||
|
||||
toast({
|
||||
title: "Saved successfully",
|
||||
description: "Whitelist settings have been saved"
|
||||
title: t('resourceWhitelistSave'),
|
||||
description: t('resourceWhitelistSaveDescription')
|
||||
});
|
||||
router.refresh();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to save whitelist",
|
||||
title: t('resourceErrorWhitelistSave'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while saving the whitelist"
|
||||
t('resourceErrorWhitelistSaveDescription')
|
||||
)
|
||||
});
|
||||
} finally {
|
||||
|
@ -281,18 +284,18 @@ export default function ResourceAuthenticationPage() {
|
|||
});
|
||||
|
||||
toast({
|
||||
title: "Saved successfully",
|
||||
description: "Authentication settings have been saved"
|
||||
title: t('resourceAuthSettingsSave'),
|
||||
description: t('resourceAuthSettingsSaveDescription')
|
||||
});
|
||||
router.refresh();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to set roles",
|
||||
title: t('resourceErrorUsersRolesSave'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while setting the roles"
|
||||
t('resourceErrorUsersRolesSaveDescription')
|
||||
)
|
||||
});
|
||||
} finally {
|
||||
|
@ -308,9 +311,8 @@ export default function ResourceAuthenticationPage() {
|
|||
})
|
||||
.then(() => {
|
||||
toast({
|
||||
title: "Resource password removed",
|
||||
description:
|
||||
"The resource password has been removed successfully"
|
||||
title: t('resourcePasswordRemove'),
|
||||
description: t('resourcePasswordRemoveDescription')
|
||||
});
|
||||
|
||||
updateAuthInfo({
|
||||
|
@ -321,10 +323,10 @@ export default function ResourceAuthenticationPage() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error removing resource password",
|
||||
title: t('resourceErrorPasswordRemove'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while removing the resource password"
|
||||
t('resourceErrorPasswordRemoveDescription')
|
||||
)
|
||||
});
|
||||
})
|
||||
|
@ -339,9 +341,8 @@ export default function ResourceAuthenticationPage() {
|
|||
})
|
||||
.then(() => {
|
||||
toast({
|
||||
title: "Resource pincode removed",
|
||||
description:
|
||||
"The resource password has been removed successfully"
|
||||
title: t('resourcePincodeRemove'),
|
||||
description: t('resourcePincodeRemoveDescription')
|
||||
});
|
||||
|
||||
updateAuthInfo({
|
||||
|
@ -352,10 +353,10 @@ export default function ResourceAuthenticationPage() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error removing resource pincode",
|
||||
title: t('resourceErrorPincodeRemove'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while removing the resource pincode"
|
||||
t('resourceErrorPincodeRemoveDescription')
|
||||
)
|
||||
});
|
||||
})
|
||||
|
@ -400,18 +401,17 @@ export default function ResourceAuthenticationPage() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
Users & Roles
|
||||
{t('resourceUsersRoles')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Configure which users and roles can visit this
|
||||
resource
|
||||
{t('resourceUsersRolesDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
<SwitchInput
|
||||
id="sso-toggle"
|
||||
label="Use Platform SSO"
|
||||
description="Existing users will only have to log in once for all resources that have this enabled."
|
||||
label={t('ssoUse')}
|
||||
description={t('ssoUseDescription')}
|
||||
defaultChecked={resource.sso}
|
||||
onCheckedChange={(val) => setSsoEnabled(val)}
|
||||
/>
|
||||
|
@ -431,7 +431,7 @@ export default function ResourceAuthenticationPage() {
|
|||
name="roles"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col items-start">
|
||||
<FormLabel>Roles</FormLabel>
|
||||
<FormLabel>{t('roles')}</FormLabel>
|
||||
<FormControl>
|
||||
<TagInput
|
||||
{...field}
|
||||
|
@ -441,7 +441,7 @@ export default function ResourceAuthenticationPage() {
|
|||
setActiveTagIndex={
|
||||
setActiveRolesTagIndex
|
||||
}
|
||||
placeholder="Select a role"
|
||||
placeholder={t('accessRoleSelect2')}
|
||||
size="sm"
|
||||
tags={
|
||||
usersRolesForm.getValues()
|
||||
|
@ -475,8 +475,7 @@ export default function ResourceAuthenticationPage() {
|
|||
</FormControl>
|
||||
<FormMessage />
|
||||
<FormDescription>
|
||||
Admins can always access
|
||||
this resource.
|
||||
{t('resourceRoleDescription')}
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
|
@ -486,7 +485,7 @@ export default function ResourceAuthenticationPage() {
|
|||
name="users"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col items-start">
|
||||
<FormLabel>Users</FormLabel>
|
||||
<FormLabel>{t('users')}</FormLabel>
|
||||
<FormControl>
|
||||
<TagInput
|
||||
{...field}
|
||||
|
@ -496,7 +495,7 @@ export default function ResourceAuthenticationPage() {
|
|||
setActiveTagIndex={
|
||||
setActiveUsersTagIndex
|
||||
}
|
||||
placeholder="Select a user"
|
||||
placeholder={t('accessUserSelect')}
|
||||
tags={
|
||||
usersRolesForm.getValues()
|
||||
.users
|
||||
|
@ -544,7 +543,7 @@ export default function ResourceAuthenticationPage() {
|
|||
disabled={loadingSaveUsersRoles}
|
||||
form="users-roles-form"
|
||||
>
|
||||
Save Users & Roles
|
||||
{t('resourceUsersRolesSubmit')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
@ -552,11 +551,10 @@ export default function ResourceAuthenticationPage() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
Authentication Methods
|
||||
{t('resourceAuthMethods')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Allow access to the resource via additional auth
|
||||
methods
|
||||
{t('resourceAuthMethodsDescriptions')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -568,7 +566,7 @@ export default function ResourceAuthenticationPage() {
|
|||
<Key />
|
||||
<span>
|
||||
Password Protection{" "}
|
||||
{authInfo.password ? "Enabled" : "Disabled"}
|
||||
{authInfo.password ? t('enabled') : t('disabled')}
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
|
@ -581,8 +579,8 @@ export default function ResourceAuthenticationPage() {
|
|||
loading={loadingRemoveResourcePassword}
|
||||
>
|
||||
{authInfo.password
|
||||
? "Remove Password"
|
||||
: "Add Password"}
|
||||
? t('passwordRemove')
|
||||
: t('passwordAdd')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
@ -593,8 +591,7 @@ export default function ResourceAuthenticationPage() {
|
|||
>
|
||||
<Binary />
|
||||
<span>
|
||||
PIN Code Protection{" "}
|
||||
{authInfo.pincode ? "Enabled" : "Disabled"}
|
||||
{t('resourcePincodeProtection', {status: authInfo.pincode ? t('enabled') : t('disabled')})}
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
|
@ -607,8 +604,8 @@ export default function ResourceAuthenticationPage() {
|
|||
loading={loadingRemoveResourcePincode}
|
||||
>
|
||||
{authInfo.pincode
|
||||
? "Remove PIN Code"
|
||||
: "Add PIN Code"}
|
||||
? t('pincodeRemove')
|
||||
: t('pincodeAdd')}
|
||||
</Button>
|
||||
</div>
|
||||
</SettingsSectionBody>
|
||||
|
@ -617,11 +614,10 @@ export default function ResourceAuthenticationPage() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
One-time Passwords
|
||||
{t('otpEmailTitle')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Require email-based authentication for resource
|
||||
access
|
||||
{t('otpEmailTitleDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -629,16 +625,16 @@ export default function ResourceAuthenticationPage() {
|
|||
<Alert variant="neutral" className="mb-4">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">
|
||||
SMTP Required
|
||||
{t('otpEmailSmtpRequired')}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
SMTP must be enabled on the server to use one-time password authentication.
|
||||
{t('otpEmailSmtpRequiredDescription')}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<SwitchInput
|
||||
id="whitelist-toggle"
|
||||
label="Email Whitelist"
|
||||
label={t('otpEmailWhitelist')}
|
||||
defaultChecked={resource.emailWhitelistEnabled}
|
||||
onCheckedChange={setWhitelistEnabled}
|
||||
disabled={!env.email.emailEnabled}
|
||||
|
@ -654,8 +650,8 @@ export default function ResourceAuthenticationPage() {
|
|||
<FormItem>
|
||||
<FormLabel>
|
||||
<InfoPopup
|
||||
text="Whitelisted Emails"
|
||||
info="Only users with these email addresses will be able to access this resource. They will be prompted to enter a one-time password sent to their email. Wildcards (*@example.com) can be used to allow any email address from a domain."
|
||||
text={t('otpEmailWhitelistList')}
|
||||
info={t('otpEmailWhitelistListDescription')}
|
||||
/>
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
|
@ -678,8 +674,7 @@ export default function ResourceAuthenticationPage() {
|
|||
.regex(
|
||||
/^\*@[\w.-]+\.[a-zA-Z]{2,}$/,
|
||||
{
|
||||
message:
|
||||
"Invalid email address. Wildcard (*) must be the entire local part."
|
||||
message: t('otpEmailErrorInvalid')
|
||||
}
|
||||
)
|
||||
)
|
||||
|
@ -690,7 +685,7 @@ export default function ResourceAuthenticationPage() {
|
|||
setActiveTagIndex={
|
||||
setActiveEmailTagIndex
|
||||
}
|
||||
placeholder="Enter an email"
|
||||
placeholder={t('otpEmailEnter')}
|
||||
tags={
|
||||
whitelistForm.getValues()
|
||||
.emails
|
||||
|
@ -713,9 +708,7 @@ export default function ResourceAuthenticationPage() {
|
|||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Press enter to add an
|
||||
email after typing it in
|
||||
the input field.
|
||||
{t('otpEmailEnterDescription')}
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
|
@ -731,7 +724,7 @@ export default function ResourceAuthenticationPage() {
|
|||
loading={loadingSaveWhitelist}
|
||||
disabled={loadingSaveWhitelist}
|
||||
>
|
||||
Save Whitelist
|
||||
{t('otpEmailWhitelistSave')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
|
|
@ -65,6 +65,9 @@ import {
|
|||
updateResourceRule
|
||||
} from "@server/routers/resource";
|
||||
import { SwitchInput } from "@app/components/SwitchInput";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const GeneralFormSchema = z
|
||||
.object({
|
||||
|
@ -88,7 +91,7 @@ const GeneralFormSchema = z
|
|||
return true;
|
||||
},
|
||||
{
|
||||
message: "Invalid port number",
|
||||
message: t('proxyErrorInvalidPort'),
|
||||
path: ["proxyPort"]
|
||||
}
|
||||
)
|
||||
|
@ -100,7 +103,7 @@ const GeneralFormSchema = z
|
|||
return true;
|
||||
},
|
||||
{
|
||||
message: "Invalid subdomain",
|
||||
message: t('subdomainErrorInvalid'),
|
||||
path: ["subdomain"]
|
||||
}
|
||||
);
|
||||
|
@ -174,10 +177,10 @@ export default function GeneralForm() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error fetching domains",
|
||||
title: t('domainErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred when fetching the domains"
|
||||
t('domainErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -216,18 +219,18 @@ export default function GeneralForm() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to update resource",
|
||||
title: t('resourceErrorUpdate'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while updating the resource"
|
||||
t('resourceErrorUpdateDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
if (res && res.status === 200) {
|
||||
toast({
|
||||
title: "Resource updated",
|
||||
description: "The resource has been updated successfully"
|
||||
title: t('resourceUpdated'),
|
||||
description: t('resourceUpdatedDescription')
|
||||
});
|
||||
|
||||
const resource = res.data.data;
|
||||
|
@ -255,18 +258,18 @@ export default function GeneralForm() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to transfer resource",
|
||||
title: t('resourceErrorTransfer'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while transferring the resource"
|
||||
t('resourceErrorTransferDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
if (res && res.status === 200) {
|
||||
toast({
|
||||
title: "Resource transferred",
|
||||
description: "The resource has been transferred successfully"
|
||||
title: t('resourceTransferred'),
|
||||
description: t('resourceTransferredDescription')
|
||||
});
|
||||
router.refresh();
|
||||
|
||||
|
@ -290,10 +293,10 @@ export default function GeneralForm() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to toggle resource",
|
||||
title: t('resourceErrorToggle'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while updating the resource"
|
||||
t('resourceErrorToggleDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -308,15 +311,15 @@ export default function GeneralForm() {
|
|||
<SettingsContainer>
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>Visibility</SettingsSectionTitle>
|
||||
<SettingsSectionTitle>{t('resourceVisibilityTitle')}</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Completely enable or disable resource visibility
|
||||
{t('resourceVisibilityTitleDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
<SwitchInput
|
||||
id="enable-resource"
|
||||
label="Enable Resource"
|
||||
label={t('resourceEnable')}
|
||||
defaultChecked={resource.enabled}
|
||||
onCheckedChange={async (val) => {
|
||||
await toggleResourceEnabled(val);
|
||||
|
@ -328,10 +331,10 @@ export default function GeneralForm() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
General Settings
|
||||
{t('resourceGeneral')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Configure the general settings for this resource
|
||||
{t('resourceGeneralDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
|
||||
|
@ -348,7 +351,7 @@ export default function GeneralForm() {
|
|||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormLabel>{t('name')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
|
@ -367,7 +370,7 @@ export default function GeneralForm() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Domain Type
|
||||
{t('domainType')}
|
||||
</FormLabel>
|
||||
<Select
|
||||
value={
|
||||
|
@ -398,11 +401,10 @@ export default function GeneralForm() {
|
|||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="subdomain">
|
||||
Subdomain
|
||||
{t('subdomain')}
|
||||
</SelectItem>
|
||||
<SelectItem value="basedomain">
|
||||
Base
|
||||
Domain
|
||||
{t('baseDomain')}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
@ -416,7 +418,7 @@ export default function GeneralForm() {
|
|||
{domainType === "subdomain" ? (
|
||||
<div className="w-fill space-y-2">
|
||||
<FormLabel>
|
||||
Subdomain
|
||||
{t('subdomain')}
|
||||
</FormLabel>
|
||||
<div className="flex">
|
||||
<div className="w-1/2">
|
||||
|
@ -502,7 +504,7 @@ export default function GeneralForm() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Base Domain
|
||||
{t('baseDomain')}
|
||||
</FormLabel>
|
||||
<Select
|
||||
onValueChange={
|
||||
|
@ -556,7 +558,7 @@ export default function GeneralForm() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Port Number
|
||||
{t('resourcePortNumber')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
|
@ -596,7 +598,7 @@ export default function GeneralForm() {
|
|||
disabled={saveLoading}
|
||||
form="general-settings-form"
|
||||
>
|
||||
Save General Settings
|
||||
{t('saveGeneralSettings')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
@ -604,10 +606,10 @@ export default function GeneralForm() {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
Transfer Resource
|
||||
{t('resourceTransfer')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Transfer this resource to a different site
|
||||
{t('resourceTransferDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
|
||||
|
@ -627,7 +629,7 @@ export default function GeneralForm() {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Destination Site
|
||||
{t('siteDestination')}
|
||||
</FormLabel>
|
||||
<Popover
|
||||
open={open}
|
||||
|
@ -652,16 +654,16 @@ export default function GeneralForm() {
|
|||
site.siteId ===
|
||||
field.value
|
||||
)?.name
|
||||
: "Select site"}
|
||||
: t('siteSelect')}
|
||||
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Search sites" />
|
||||
<CommandInput placeholder={t('searchSites')} />
|
||||
<CommandEmpty>
|
||||
No sites found.
|
||||
{t('sitesNotFound')}
|
||||
</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{sites.map(
|
||||
|
@ -716,7 +718,7 @@ export default function GeneralForm() {
|
|||
disabled={transferLoading}
|
||||
form="transfer-form"
|
||||
>
|
||||
Transfer Resource
|
||||
{t('resourceTransferSubmit')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
|
|
@ -73,6 +73,7 @@ import {
|
|||
CollapsibleContent,
|
||||
CollapsibleTrigger
|
||||
} from "@app/components/ui/collapsible";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const addTargetSchema = z.object({
|
||||
ip: z.string().refine(isTargetValid),
|
||||
|
@ -92,6 +93,8 @@ type LocalTarget = Omit<
|
|||
"protocol"
|
||||
>;
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const proxySettingsSchema = z.object({
|
||||
setHostHeader: z
|
||||
.string()
|
||||
|
@ -104,8 +107,7 @@ const proxySettingsSchema = z.object({
|
|||
return true;
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Invalid custom Host Header value. Use domain name format, or save empty to unset custom Host Header."
|
||||
message: t('proxyErrorInvalidHeader')
|
||||
}
|
||||
)
|
||||
});
|
||||
|
@ -123,8 +125,7 @@ const tlsSettingsSchema = z.object({
|
|||
return true;
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Invalid TLS Server Name. Use domain name format, or save empty to remove the TLS Server Name."
|
||||
message: t('proxyErrorTls')
|
||||
}
|
||||
)
|
||||
});
|
||||
|
@ -199,10 +200,10 @@ export default function ReverseProxyTargets(props: {
|
|||
console.error(err);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to fetch targets",
|
||||
title: t('targetErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
err,
|
||||
"An error occurred while fetching targets"
|
||||
t('targetErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
} finally {
|
||||
|
@ -224,10 +225,10 @@ export default function ReverseProxyTargets(props: {
|
|||
console.error(err);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to fetch resource",
|
||||
title: t('siteErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
err,
|
||||
"An error occurred while fetching resource"
|
||||
t('siteErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -247,8 +248,8 @@ export default function ReverseProxyTargets(props: {
|
|||
if (isDuplicate) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Duplicate target",
|
||||
description: "A target with these settings already exists"
|
||||
title: t('targetErrorDuplicate'),
|
||||
description: t('targetErrorDuplicateDescription')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -260,8 +261,8 @@ export default function ReverseProxyTargets(props: {
|
|||
if (!isIPInSubnet(targetIp, subnet)) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid target IP",
|
||||
description: "Target IP must be within the site subnet"
|
||||
title: t('targetWireGuardErrorInvalidIp'),
|
||||
description: t('targetWireGuardErrorInvalidIpDescription')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -339,8 +340,8 @@ export default function ReverseProxyTargets(props: {
|
|||
updateResource({ stickySession: stickySessionData.stickySession });
|
||||
|
||||
toast({
|
||||
title: "Targets updated",
|
||||
description: "Targets and settings updated successfully"
|
||||
title: t('targetsUpdated'),
|
||||
description: t('targetsUpdatedDescription')
|
||||
});
|
||||
|
||||
setTargetsToRemove([]);
|
||||
|
@ -349,10 +350,10 @@ export default function ReverseProxyTargets(props: {
|
|||
console.error(err);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to update targets",
|
||||
title: t('targetsErrorUpdate'),
|
||||
description: formatAxiosError(
|
||||
err,
|
||||
"An error occurred while updating targets"
|
||||
t('targetsErrorUpdateDescription')
|
||||
)
|
||||
});
|
||||
} finally {
|
||||
|
@ -373,17 +374,17 @@ export default function ReverseProxyTargets(props: {
|
|||
tlsServerName: data.tlsServerName || null
|
||||
});
|
||||
toast({
|
||||
title: "TLS settings updated",
|
||||
description: "Your TLS settings have been updated successfully"
|
||||
title: t('targetTlsUpdate'),
|
||||
description: t('targetTlsUpdateDescription')
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to update TLS settings",
|
||||
title: t('targetErrorTlsUpdate'),
|
||||
description: formatAxiosError(
|
||||
err,
|
||||
"An error occurred while updating TLS settings"
|
||||
t('targetErrorTlsUpdateDescription')
|
||||
)
|
||||
});
|
||||
} finally {
|
||||
|
@ -402,18 +403,17 @@ export default function ReverseProxyTargets(props: {
|
|||
setHostHeader: data.setHostHeader || null
|
||||
});
|
||||
toast({
|
||||
title: "Proxy settings updated",
|
||||
description:
|
||||
"Your proxy settings have been updated successfully"
|
||||
title: t('proxyUpdated'),
|
||||
description: t('proxyUpdatedDescription')
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to update proxy settings",
|
||||
title: t('proxyErrorUpdate'),
|
||||
description: formatAxiosError(
|
||||
err,
|
||||
"An error occurred while updating proxy settings"
|
||||
t('proxyErrorUpdateDescription')
|
||||
)
|
||||
});
|
||||
} finally {
|
||||
|
@ -424,7 +424,7 @@ export default function ReverseProxyTargets(props: {
|
|||
const columns: ColumnDef<LocalTarget>[] = [
|
||||
{
|
||||
accessorKey: "ip",
|
||||
header: "IP / Hostname",
|
||||
header: t('targetAddr'),
|
||||
cell: ({ row }) => (
|
||||
<Input
|
||||
defaultValue={row.original.ip}
|
||||
|
@ -439,7 +439,7 @@ export default function ReverseProxyTargets(props: {
|
|||
},
|
||||
{
|
||||
accessorKey: "port",
|
||||
header: "Port",
|
||||
header: t('targetPort'),
|
||||
cell: ({ row }) => (
|
||||
<Input
|
||||
type="number"
|
||||
|
@ -455,7 +455,7 @@ export default function ReverseProxyTargets(props: {
|
|||
},
|
||||
// {
|
||||
// accessorKey: "protocol",
|
||||
// header: "Protocol",
|
||||
// header: t('targetProtocol'),
|
||||
// cell: ({ row }) => (
|
||||
// <Select
|
||||
// defaultValue={row.original.protocol!}
|
||||
|
@ -473,7 +473,7 @@ export default function ReverseProxyTargets(props: {
|
|||
// },
|
||||
{
|
||||
accessorKey: "enabled",
|
||||
header: "Enabled",
|
||||
header: t('enabled'),
|
||||
cell: ({ row }) => (
|
||||
<Switch
|
||||
defaultChecked={row.original.enabled}
|
||||
|
@ -500,7 +500,7 @@ export default function ReverseProxyTargets(props: {
|
|||
variant="outline"
|
||||
onClick={() => removeTarget(row.original.targetId)}
|
||||
>
|
||||
Delete
|
||||
{t('delete')}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
|
@ -511,7 +511,7 @@ export default function ReverseProxyTargets(props: {
|
|||
if (resource.http) {
|
||||
const methodCol: ColumnDef<LocalTarget> = {
|
||||
accessorKey: "method",
|
||||
header: "Method",
|
||||
header: t('method'),
|
||||
cell: ({ row }) => (
|
||||
<Select
|
||||
defaultValue={row.original.method ?? ""}
|
||||
|
@ -560,10 +560,10 @@ export default function ReverseProxyTargets(props: {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
HTTPS & TLS Settings
|
||||
{t('targetTlsSettings')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Configure TLS settings for your resource
|
||||
{t('targetTlsSettingsDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -611,12 +611,12 @@ export default function ReverseProxyTargets(props: {
|
|||
className="p-0 flex items-center justify-start gap-2 w-full"
|
||||
>
|
||||
<h4 className="text-sm font-semibold">
|
||||
Advanced TLS Settings
|
||||
{t('targetTlsSettingsAdvanced')}
|
||||
</h4>
|
||||
<div>
|
||||
<ChevronsUpDown className="h-4 w-4" />
|
||||
<span className="sr-only">
|
||||
Toggle
|
||||
{t('toggle')}
|
||||
</span>
|
||||
</div>
|
||||
</Button>
|
||||
|
@ -631,17 +631,13 @@ export default function ReverseProxyTargets(props: {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
TLS Server Name
|
||||
(SNI)
|
||||
{t('targetTlsSni')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
The TLS Server Name
|
||||
to use for SNI.
|
||||
Leave empty to use
|
||||
the default.
|
||||
{t('targetTlsSniDescription')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
@ -659,7 +655,7 @@ export default function ReverseProxyTargets(props: {
|
|||
loading={httpsTlsLoading}
|
||||
form="tls-settings-form"
|
||||
>
|
||||
Save Settings
|
||||
{t('targetTlsSubmit')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
@ -668,10 +664,10 @@ export default function ReverseProxyTargets(props: {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
Targets Configuration
|
||||
{t('targets')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Set up targets to route traffic to your services
|
||||
{t('targetsDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -693,8 +689,8 @@ export default function ReverseProxyTargets(props: {
|
|||
<FormControl>
|
||||
<SwitchInput
|
||||
id="sticky-toggle"
|
||||
label="Enable Sticky Sessions"
|
||||
description="Keep connections on the same backend target for their entire session."
|
||||
label={t('targetStickySessions')}
|
||||
description={t('targetStickySessionsDescription')}
|
||||
defaultChecked={
|
||||
field.value
|
||||
}
|
||||
|
@ -725,7 +721,7 @@ export default function ReverseProxyTargets(props: {
|
|||
name="method"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Method</FormLabel>
|
||||
<FormLabel>{t('method')}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
value={
|
||||
|
@ -742,7 +738,7 @@ export default function ReverseProxyTargets(props: {
|
|||
}}
|
||||
>
|
||||
<SelectTrigger id="method">
|
||||
<SelectValue placeholder="Select method" />
|
||||
<SelectValue placeholder={t('methodSelect')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="http">
|
||||
|
@ -768,7 +764,7 @@ export default function ReverseProxyTargets(props: {
|
|||
name="ip"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>IP / Hostname</FormLabel>
|
||||
<FormLabel>{t('targetAddr')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input id="ip" {...field} />
|
||||
</FormControl>
|
||||
|
@ -781,7 +777,7 @@ export default function ReverseProxyTargets(props: {
|
|||
name="port"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Port</FormLabel>
|
||||
<FormLabel>{t('targetPort')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="port"
|
||||
|
@ -805,7 +801,7 @@ export default function ReverseProxyTargets(props: {
|
|||
)
|
||||
}
|
||||
>
|
||||
Add Target
|
||||
{t('targetSubmit')}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -849,14 +845,13 @@ export default function ReverseProxyTargets(props: {
|
|||
colSpan={columns.length}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
No targets. Add a target using the form.
|
||||
{t('targetNoOne')}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
<TableCaption>
|
||||
Adding more than one target above will enable load
|
||||
balancing.
|
||||
{t('targetNoOneDescription')}
|
||||
</TableCaption>
|
||||
</Table>
|
||||
</SettingsSectionBody>
|
||||
|
@ -867,7 +862,7 @@ export default function ReverseProxyTargets(props: {
|
|||
disabled={targetsLoading}
|
||||
form="targets-settings-form"
|
||||
>
|
||||
Save Targets
|
||||
{t('targetsSubmit')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
@ -876,10 +871,10 @@ export default function ReverseProxyTargets(props: {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
Additional Proxy Settings
|
||||
{t('proxyAdditional')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Configure how your resource handles proxy settings
|
||||
{t('proxyAdditionalDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -898,15 +893,13 @@ export default function ReverseProxyTargets(props: {
|
|||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Custom Host Header
|
||||
{t('proxyCustomHeader')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
The host header to set when
|
||||
proxying requests. Leave
|
||||
empty to use the default.
|
||||
{t('proxyCustomHeaderDescription')}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
@ -922,7 +915,7 @@ export default function ReverseProxyTargets(props: {
|
|||
loading={proxySettingsLoading}
|
||||
form="proxy-settings-form"
|
||||
>
|
||||
Save Proxy Settings
|
||||
{t('proxyAdditionalSubmit')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
@ -937,7 +930,7 @@ function isIPInSubnet(subnet: string, ip: string): boolean {
|
|||
const mask = parseInt(maskBits);
|
||||
|
||||
if (mask < 0 || mask > 32) {
|
||||
throw new Error("Invalid subnet mask. Must be between 0 and 32.");
|
||||
throw new Error(t('subnetMaskErrorInvalid'));
|
||||
}
|
||||
|
||||
// Convert IP addresses to binary numbers
|
||||
|
@ -955,14 +948,14 @@ function ipToNumber(ip: string): number {
|
|||
// Validate IP address format
|
||||
const parts = ip.split(".");
|
||||
if (parts.length !== 4) {
|
||||
throw new Error("Invalid IP address format");
|
||||
throw new Error(t('ipAddressErrorInvalidFormat'));
|
||||
}
|
||||
|
||||
// Convert IP octets to 32-bit number
|
||||
return parts.reduce((num, octet) => {
|
||||
const oct = parseInt(octet);
|
||||
if (isNaN(oct) || oct < 0 || oct > 255) {
|
||||
throw new Error("Invalid IP address octet");
|
||||
throw new Error(t('ipAddressErrorInvalidOctet'));
|
||||
}
|
||||
return (num << 8) + oct;
|
||||
}, 0);
|
||||
|
|
|
@ -73,6 +73,7 @@ import {
|
|||
} from "@server/lib/validators";
|
||||
import { Switch } from "@app/components/ui/switch";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
// Schema for rule validation
|
||||
const addRuleSchema = z.object({
|
||||
|
@ -87,16 +88,18 @@ type LocalRule = ArrayElement<ListResourceRulesResponse["rules"]> & {
|
|||
updated?: boolean;
|
||||
};
|
||||
|
||||
enum RuleAction {
|
||||
ACCEPT = "Always Allow",
|
||||
DROP = "Always Deny"
|
||||
}
|
||||
const t = useTranslations();
|
||||
|
||||
enum RuleMatch {
|
||||
PATH = "Path",
|
||||
IP = "IP",
|
||||
CIDR = "IP Range"
|
||||
}
|
||||
const RuleAction = {
|
||||
ACCEPT: t('alwaysAllow'),
|
||||
DROP: t('alwaysDeny')
|
||||
} as const;
|
||||
|
||||
const RuleMatch = {
|
||||
PATH: t('path'),
|
||||
IP: "IP",
|
||||
CIDR: t('ipAddressRange')
|
||||
} as const;
|
||||
|
||||
export default function ResourceRules(props: {
|
||||
params: Promise<{ resourceId: number }>;
|
||||
|
@ -133,10 +136,10 @@ export default function ResourceRules(props: {
|
|||
console.error(err);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to fetch rules",
|
||||
title: t('rulesErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
err,
|
||||
"An error occurred while fetching rules"
|
||||
t('rulesErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
} finally {
|
||||
|
@ -157,8 +160,8 @@ export default function ResourceRules(props: {
|
|||
if (isDuplicate) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Duplicate rule",
|
||||
description: "A rule with these settings already exists"
|
||||
title: t('rulesErrorDuplicate'),
|
||||
description: t('rulesErrorDuplicateDescription')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -166,8 +169,8 @@ export default function ResourceRules(props: {
|
|||
if (data.match === "CIDR" && !isValidCIDR(data.value)) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid CIDR",
|
||||
description: "Please enter a valid CIDR value"
|
||||
title: t('rulesErrorInvalidIpAddressRange'),
|
||||
description: t('rulesErrorInvalidIpAddressRangeDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -175,8 +178,8 @@ export default function ResourceRules(props: {
|
|||
if (data.match === "PATH" && !isValidUrlGlobPattern(data.value)) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid URL path",
|
||||
description: "Please enter a valid URL path value"
|
||||
title: t('rulesErrorInvalidUrl'),
|
||||
description: t('rulesErrorInvalidUrlDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -184,8 +187,8 @@ export default function ResourceRules(props: {
|
|||
if (data.match === "IP" && !isValidIP(data.value)) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid IP",
|
||||
description: "Please enter a valid IP address"
|
||||
title: t('rulesErrorInvalidIpAddress'),
|
||||
description: t('rulesErrorInvalidIpAddressDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -240,10 +243,10 @@ export default function ResourceRules(props: {
|
|||
console.error(err);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Failed to update rules",
|
||||
title: t('rulesErrorUpdate'),
|
||||
description: formatAxiosError(
|
||||
err,
|
||||
"An error occurred while updating rules"
|
||||
t('rulesErrorUpdateDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -253,8 +256,8 @@ export default function ResourceRules(props: {
|
|||
updateResource({ applyRules: val });
|
||||
|
||||
toast({
|
||||
title: "Enable Rules",
|
||||
description: "Rule evaluation has been updated"
|
||||
title: t('rulesUpdated'),
|
||||
description: t('rulesUpdatedDescription')
|
||||
});
|
||||
router.refresh();
|
||||
}
|
||||
|
@ -263,11 +266,11 @@ export default function ResourceRules(props: {
|
|||
function getValueHelpText(type: string) {
|
||||
switch (type) {
|
||||
case "CIDR":
|
||||
return "Enter an address in CIDR format (e.g., 103.21.244.0/22)";
|
||||
return t('rulesMatchIpAddressRangeDescription');
|
||||
case "IP":
|
||||
return "Enter an IP address (e.g., 103.21.244.12)";
|
||||
return t('rulesMatchIpAddress');
|
||||
case "PATH":
|
||||
return "Enter a URL path or pattern (e.g., /api/v1/todos or /api/v1/*)";
|
||||
return t('rulesMatchUrl');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,8 +289,8 @@ export default function ResourceRules(props: {
|
|||
if (rule.match === "CIDR" && !isValidCIDR(rule.value)) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid CIDR",
|
||||
description: "Please enter a valid CIDR value"
|
||||
title: t('rulesErrorInvalidIpAddressRange'),
|
||||
description: t('rulesErrorInvalidIpAddressRangeDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -298,8 +301,8 @@ export default function ResourceRules(props: {
|
|||
) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid URL path",
|
||||
description: "Please enter a valid URL path value"
|
||||
title: t('rulesErrorInvalidUrl'),
|
||||
description: t('rulesErrorInvalidUrlDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -307,8 +310,8 @@ export default function ResourceRules(props: {
|
|||
if (rule.match === "IP" && !isValidIP(rule.value)) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid IP",
|
||||
description: "Please enter a valid IP address"
|
||||
title: t('rulesErrorInvalidIpAddress'),
|
||||
description: t('rulesErrorInvalidIpAddressDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -317,8 +320,8 @@ export default function ResourceRules(props: {
|
|||
if (rule.priority === undefined) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid Priority",
|
||||
description: "Please enter a valid priority"
|
||||
title: t('rulesErrorInvalidPriority'),
|
||||
description: t('rulesErrorInvalidPriorityDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -329,8 +332,8 @@ export default function ResourceRules(props: {
|
|||
if (priorities.length !== new Set(priorities).size) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Duplicate Priorities",
|
||||
description: "Please enter unique priorities"
|
||||
title: t('rulesErrorDuplicatePriority'),
|
||||
description: t('rulesErrorDuplicatePriorityDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -369,8 +372,8 @@ export default function ResourceRules(props: {
|
|||
}
|
||||
|
||||
toast({
|
||||
title: "Rules updated",
|
||||
description: "Rules updated successfully"
|
||||
title: t('ruleUpdated'),
|
||||
description: t('ruleUpdatedDescription')
|
||||
});
|
||||
|
||||
setRulesToRemove([]);
|
||||
|
@ -379,10 +382,10 @@ export default function ResourceRules(props: {
|
|||
console.error(err);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Operation failed",
|
||||
title: t('ruleErrorUpdate'),
|
||||
description: formatAxiosError(
|
||||
err,
|
||||
"An error occurred during the save operation"
|
||||
t('ruleErrorUpdateDescription')
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -400,7 +403,7 @@ export default function ResourceRules(props: {
|
|||
column.toggleSorting(column.getIsSorted() === "asc")
|
||||
}
|
||||
>
|
||||
Priority
|
||||
{t('rulesPriority')}
|
||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
|
@ -420,8 +423,8 @@ export default function ResourceRules(props: {
|
|||
if (!parsed.data) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Invalid IP",
|
||||
description: "Please enter a valid priority"
|
||||
title: t('rulesErrorInvalidIpAddress'), // correct priority or IP?
|
||||
description: t('rulesErrorInvalidPriorityDescription')
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
|
@ -436,7 +439,7 @@ export default function ResourceRules(props: {
|
|||
},
|
||||
{
|
||||
accessorKey: "action",
|
||||
header: "Action",
|
||||
header: t('rulesAction'),
|
||||
cell: ({ row }) => (
|
||||
<Select
|
||||
defaultValue={row.original.action}
|
||||
|
@ -458,7 +461,7 @@ export default function ResourceRules(props: {
|
|||
},
|
||||
{
|
||||
accessorKey: "match",
|
||||
header: "Match Type",
|
||||
header: t('rulesMatchType'),
|
||||
cell: ({ row }) => (
|
||||
<Select
|
||||
defaultValue={row.original.match}
|
||||
|
@ -479,7 +482,7 @@ export default function ResourceRules(props: {
|
|||
},
|
||||
{
|
||||
accessorKey: "value",
|
||||
header: "Value",
|
||||
header: t('value'),
|
||||
cell: ({ row }) => (
|
||||
<Input
|
||||
defaultValue={row.original.value}
|
||||
|
@ -494,7 +497,7 @@ export default function ResourceRules(props: {
|
|||
},
|
||||
{
|
||||
accessorKey: "enabled",
|
||||
header: "Enabled",
|
||||
header: t('enabled'),
|
||||
cell: ({ row }) => (
|
||||
<Switch
|
||||
defaultChecked={row.original.enabled}
|
||||
|
@ -512,7 +515,7 @@ export default function ResourceRules(props: {
|
|||
variant="outline"
|
||||
onClick={() => removeRule(row.original.ruleId)}
|
||||
>
|
||||
Delete
|
||||
{t('delete')}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
|
@ -542,46 +545,40 @@ export default function ResourceRules(props: {
|
|||
<SettingsContainer>
|
||||
<Alert className="hidden md:block">
|
||||
<InfoIcon className="h-4 w-4" />
|
||||
<AlertTitle className="font-semibold">About Rules</AlertTitle>
|
||||
<AlertTitle className="font-semibold">{t('rulesAbout')}</AlertTitle>
|
||||
<AlertDescription className="mt-4">
|
||||
<div className="space-y-1 mb-4">
|
||||
<p>
|
||||
Rules allow you to control access to your resource
|
||||
based on a set of criteria. You can create rules to
|
||||
allow or deny access based on IP address or URL
|
||||
path.
|
||||
{t('rulesAboutDescription')}
|
||||
</p>
|
||||
</div>
|
||||
<InfoSections cols={2}>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>Actions</InfoSectionTitle>
|
||||
<InfoSectionTitle>{t('rulesActions')}</InfoSectionTitle>
|
||||
<ul className="text-sm text-muted-foreground space-y-1">
|
||||
<li className="flex items-center gap-2">
|
||||
<Check className="text-green-500 w-4 h-4" />
|
||||
Always Allow: Bypass all authentication
|
||||
methods
|
||||
{t('rulesActionAlwaysAllow')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<X className="text-red-500 w-4 h-4" />
|
||||
Always Deny: Block all requests; no
|
||||
authentication can be attempted
|
||||
{t('rulesActionAlwaysDeny')}
|
||||
</li>
|
||||
</ul>
|
||||
</InfoSection>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
Matching Criteria
|
||||
{t('rulesMatchCriteria')}
|
||||
</InfoSectionTitle>
|
||||
<ul className="text-sm text-muted-foreground space-y-1">
|
||||
<li className="flex items-center gap-2">
|
||||
Match a specific IP address
|
||||
{t('rulesMatchCriteriaIpAddress')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
Match a range of IP addresses in CIDR
|
||||
notation
|
||||
{t('rulesMatchCriteriaIpAddressRange')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
Match a URL path or pattern
|
||||
{t('rulesMatchCriteriaUrl')}
|
||||
</li>
|
||||
</ul>
|
||||
</InfoSection>
|
||||
|
@ -591,15 +588,15 @@ export default function ResourceRules(props: {
|
|||
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>Enable Rules</SettingsSectionTitle>
|
||||
<SettingsSectionTitle>{t('rulesEnable')}</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Enable or disable rule evaluation for this resource
|
||||
{t('rulesEnableDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
<SwitchInput
|
||||
id="rules-toggle"
|
||||
label="Enable Rules"
|
||||
label={t('rulesEnable')}
|
||||
defaultChecked={rulesEnabled}
|
||||
onCheckedChange={async (val) => {
|
||||
await saveApplyRules(val);
|
||||
|
@ -611,10 +608,10 @@ export default function ResourceRules(props: {
|
|||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
Resource Rules Configuration
|
||||
{t('rulesResource')}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Configure rules to control access to your resource
|
||||
{t('rulesResourceDescription')}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
|
@ -629,7 +626,7 @@ export default function ResourceRules(props: {
|
|||
name="action"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Action</FormLabel>
|
||||
<FormLabel>{t('rulesAction')}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
value={field.value}
|
||||
|
@ -659,7 +656,7 @@ export default function ResourceRules(props: {
|
|||
name="match"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Match Type</FormLabel>
|
||||
<FormLabel>{t('rulesMatchType')}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
value={field.value}
|
||||
|
@ -695,7 +692,7 @@ export default function ResourceRules(props: {
|
|||
render={({ field }) => (
|
||||
<FormItem className="space-y-0 mb-2">
|
||||
<InfoPopup
|
||||
text="Value"
|
||||
text={t('value')}
|
||||
info={
|
||||
getValueHelpText(
|
||||
addRuleForm.watch(
|
||||
|
@ -717,7 +714,7 @@ export default function ResourceRules(props: {
|
|||
className="mb-2"
|
||||
disabled={!rulesEnabled}
|
||||
>
|
||||
Add Rule
|
||||
{t('ruleSubmit')}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -760,13 +757,13 @@ export default function ResourceRules(props: {
|
|||
colSpan={columns.length}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
No rules. Add a rule using the form.
|
||||
{t('rulesNoOne')}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
<TableCaption>
|
||||
Rules are evaluated by priority in ascending order.
|
||||
{t('rulesOrder')}
|
||||
</TableCaption>
|
||||
</Table>
|
||||
</SettingsSectionBody>
|
||||
|
@ -776,7 +773,7 @@ export default function ResourceRules(props: {
|
|||
loading={loading}
|
||||
disabled={loading}
|
||||
>
|
||||
Save Rules
|
||||
{t('rulesSubmit')}
|
||||
</Button>
|
||||
</SettingsSectionFooter>
|
||||
</SettingsSection>
|
||||
|
|
|
@ -242,10 +242,10 @@ export default function Page() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error fetching sites",
|
||||
title: t('sitesErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred when fetching the sites"
|
||||
t('sitesErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -270,10 +270,10 @@ export default function Page() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error fetching domains",
|
||||
title: t('domainsErrorFetch'),
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred when fetching the domains"
|
||||
t('domainsErrorFetchDescription')
|
||||
)
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@ import { GetOrgResponse } from "@server/routers/org";
|
|||
import OrgProvider from "@app/providers/OrgProvider";
|
||||
import ResourcesSplashCard from "./ResourcesSplashCard";
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type ResourcesPageProps = {
|
||||
params: Promise<{ orgId: string }>;
|
||||
|
@ -46,14 +47,16 @@ export default async function ResourcesPage(props: ResourcesPageProps) {
|
|||
redirect(`/${params.orgId}/settings/resources`);
|
||||
}
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const resourceRows: ResourceRow[] = resources.map((resource) => {
|
||||
return {
|
||||
id: resource.resourceId,
|
||||
name: resource.name,
|
||||
orgId: params.orgId,
|
||||
domain: `${resource.ssl ? "https://" : "http://"}${resource.fullDomain}`,
|
||||
site: resource.siteName || "None",
|
||||
siteId: resource.siteId || "Unknown",
|
||||
site: resource.siteName || t('none'),
|
||||
siteId: resource.siteId || t('unknown'),
|
||||
protocol: resource.protocol,
|
||||
proxyPort: resource.proxyPort,
|
||||
http: resource.http,
|
||||
|
@ -69,8 +72,6 @@ export default async function ResourcesPage(props: ResourcesPageProps) {
|
|||
};
|
||||
});
|
||||
|
||||
const t = await getTranslations();
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <ResourcesSplashCard /> */}
|
||||
|
|
|
@ -92,7 +92,6 @@ export default function CreateShareLinkForm({
|
|||
|
||||
const { env } = useEnvContext();
|
||||
const api = createApiClient({ env });
|
||||
const t = useTranslations();
|
||||
|
||||
const [link, setLink] = useState<string | null>(null);
|
||||
const [accessTokenId, setAccessTokenId] = useState<string | null>(null);
|
||||
|
@ -111,6 +110,8 @@ export default function CreateShareLinkForm({
|
|||
}[]
|
||||
>([]);
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const timeUnits = [
|
||||
{ unit: "minutes", name: t('minutes') },
|
||||
{ unit: "hours", name: t('hours') },
|
||||
|
@ -143,8 +144,11 @@ export default function CreateShareLinkForm({
|
|||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('shareErrorFetchResource'),
|
||||
description: formatAxiosError(e, t('shareErrorFetchResourceDescription'))
|
||||
title: "Failed to fetch resources",
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while fetching the resources"
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -207,8 +211,11 @@ export default function CreateShareLinkForm({
|
|||
console.error(e);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('shareErrorCreate'),
|
||||
description: formatAxiosError(e, t('shareErrorCreateDescription'))
|
||||
title: "Failed to create share link",
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while creating the share link"
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -294,7 +301,7 @@ export default function CreateShareLinkForm({
|
|||
? getSelectedResourceName(
|
||||
field.value
|
||||
)
|
||||
: "Select resource"}
|
||||
: t('resourceSelect')}
|
||||
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
|
@ -387,7 +394,7 @@ export default function CreateShareLinkForm({
|
|||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select duration" />
|
||||
<SelectValue placeholder={t('selectDuration')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
|
@ -497,7 +504,7 @@ export default function CreateShareLinkForm({
|
|||
<div>
|
||||
<ChevronsUpDown className="h-4 w-4" />
|
||||
<span className="sr-only">
|
||||
Toggle
|
||||
{t('toggle')}
|
||||
</span>
|
||||
</div>
|
||||
</Button>
|
||||
|
@ -527,7 +534,7 @@ export default function CreateShareLinkForm({
|
|||
</CredenzaBody>
|
||||
<CredenzaFooter>
|
||||
<CredenzaClose asChild>
|
||||
<Button variant="outline">Close</Button>
|
||||
<Button variant="outline">{t('close')}</Button>
|
||||
</CredenzaClose>
|
||||
<Button
|
||||
type="button"
|
||||
|
|
|
@ -24,7 +24,7 @@ export function ShareLinksDataTable<TData, TValue>({
|
|||
<DataTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
title="Share Links"
|
||||
title={t('shareLinks')}
|
||||
searchPlaceholder={t('shareSearch')}
|
||||
searchColumn="name"
|
||||
onAdd={createShareLink}
|
||||
|
|
|
@ -4,6 +4,7 @@ import React, { useState, useEffect } from "react";
|
|||
import { Link, X, Clock, Share, ArrowRight, Lock } from "lucide-react"; // Replace with actual imports
|
||||
import { Card, CardContent } from "@app/components/ui/card";
|
||||
import { Button } from "@app/components/ui/button";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export const ShareableLinksSplash = () => {
|
||||
const [isDismissed, setIsDismissed] = useState(false);
|
||||
|
@ -22,6 +23,8 @@ export const ShareableLinksSplash = () => {
|
|||
localStorage.setItem(key, "true");
|
||||
};
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
if (isDismissed) {
|
||||
return null;
|
||||
}
|
||||
|
@ -31,7 +34,7 @@ export const ShareableLinksSplash = () => {
|
|||
<button
|
||||
onClick={handleDismiss}
|
||||
className="absolute top-2 right-2 p-2"
|
||||
aria-label="Dismiss"
|
||||
aria-label={t('dismiss')}
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
|
@ -39,26 +42,23 @@ export const ShareableLinksSplash = () => {
|
|||
<div className="space-y-4">
|
||||
<h3 className="text-xl font-semibold flex items-center gap-2">
|
||||
<Link className="text-blue-500" />
|
||||
Shareable Links
|
||||
{t('share')}
|
||||
</h3>
|
||||
<p className="text-sm">
|
||||
Create shareable links to your resources. Links provide
|
||||
temporary or unlimited access to your resource. You can
|
||||
configure the expiration duration of the link when you
|
||||
create one.
|
||||
{t('shareDescription2')}
|
||||
</p>
|
||||
<ul className="text-sm text-muted-foreground space-y-2">
|
||||
<li className="flex items-center gap-2">
|
||||
<Share className="text-green-500 w-4 h-4" />
|
||||
Easy to create and share
|
||||
{t('shareEasyCreate')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<Clock className="text-yellow-500 w-4 h-4" />
|
||||
Configurable expiration duration
|
||||
{t('shareConfigurableExpirationDuration')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<Lock className="text-red-500 w-4 h-4" />
|
||||
Secure and revocable
|
||||
{t('shareSecureAndRevocable')}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -69,8 +69,11 @@ export default function ShareLinksTable({
|
|||
async function deleteSharelink(id: string) {
|
||||
await api.delete(`/access-token/${id}`).catch((e) => {
|
||||
toast({
|
||||
title: t('shareErrorDelete'),
|
||||
description: formatAxiosError(e,t('shareErrorDeleteMessage'))
|
||||
title: "Failed to delete link",
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred deleting link"
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -78,8 +81,8 @@ export default function ShareLinksTable({
|
|||
setRows(newRows);
|
||||
|
||||
toast({
|
||||
title: t('shareDeleted'),
|
||||
description: t('shareDeletedDesciption')
|
||||
title: "Link deleted",
|
||||
description: "The link has been deleted"
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -52,16 +52,14 @@ import {
|
|||
import LoaderPlaceholder from "@app/components/PlaceHolderLoader";
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const createSiteFormSchema = z.object({
|
||||
name: z
|
||||
.string()
|
||||
.min(2, {
|
||||
message: {t('siteNameMin')}
|
||||
message: "Name must be at least 2 characters."
|
||||
})
|
||||
.max(30, {
|
||||
message: {t('siteNameMax')}
|
||||
message: "Name must not be longer than 30 characters."
|
||||
}),
|
||||
method: z.enum(["wireguard", "newt", "local"])
|
||||
});
|
||||
|
@ -117,6 +115,8 @@ export default function CreateSiteForm({
|
|||
const nameField = form.watch("name");
|
||||
const methodField = form.watch("method");
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
useEffect(() => {
|
||||
const nameIsValid = nameField?.length >= 2 && nameField?.length <= 30;
|
||||
const isFormValid = methodField === "local" || isChecked;
|
||||
|
@ -172,8 +172,8 @@ export default function CreateSiteForm({
|
|||
if (!keypair || !siteDefaults) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: {t('siteErrorCreate')},
|
||||
description: {t('siteErrorCreateKeyPair')}
|
||||
title: "Error creating site",
|
||||
description: "Key pair or site defaults not found"
|
||||
});
|
||||
setLoading?.(false);
|
||||
setIsLoading(false);
|
||||
|
@ -191,8 +191,8 @@ export default function CreateSiteForm({
|
|||
if (!siteDefaults) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: {t('siteErrorCreate')},
|
||||
description: {t('siteErrorCreateDefaults')}
|
||||
title: "Error creating site",
|
||||
description: "Site defaults not found"
|
||||
});
|
||||
setLoading?.(false);
|
||||
setIsLoading(false);
|
||||
|
@ -215,7 +215,7 @@ export default function CreateSiteForm({
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: {t('siteErrorCreate')},
|
||||
title: "Error creating site",
|
||||
description: formatAxiosError(e)
|
||||
});
|
||||
});
|
||||
|
@ -315,7 +315,7 @@ PersistentKeepalive = 5`
|
|||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="local">
|
||||
Local
|
||||
{t('local')}
|
||||
</SelectItem>
|
||||
<SelectItem
|
||||
value="newt"
|
||||
|
|
|
@ -22,8 +22,8 @@ export function SitesDataTable<TData, TValue>({
|
|||
<DataTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
title="Sites"
|
||||
searchPlaceholder={t('searchSites')}
|
||||
title={t('sites')}
|
||||
searchPlaceholder={t('searchSitesProgress')}
|
||||
searchColumn="name"
|
||||
onAdd={createSite}
|
||||
addButtonText={t('siteAdd')}
|
||||
|
|
|
@ -36,7 +36,7 @@ export const SitesSplashCard = () => {
|
|||
<button
|
||||
onClick={handleDismiss}
|
||||
className="absolute top-2 right-2 p-2"
|
||||
aria-label="Dismiss"
|
||||
aria-label={t('dismiss')}
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
|
@ -70,7 +70,7 @@ export const SitesSplashCard = () => {
|
|||
className="w-full flex items-center"
|
||||
variant="secondary"
|
||||
>
|
||||
Install Newt{" "}
|
||||
{t('siteInstallNewt')}{" "}
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</Button>
|
||||
</Link>
|
||||
|
@ -78,20 +78,19 @@ export const SitesSplashCard = () => {
|
|||
</div>
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-xl font-semibold flex items-center gap-2">
|
||||
Basic WireGuard
|
||||
{t('siteWg')}
|
||||
</h3>
|
||||
<p className="text-sm">
|
||||
Use any WireGuard client to connect. You will have to
|
||||
address your internal resources using the peer IP.
|
||||
{t('siteWgAnyClients')}
|
||||
</p>
|
||||
<ul className="text-sm text-muted-foreground space-y-2">
|
||||
<li className="flex items-center gap-2">
|
||||
<Docker className="text-purple-500 w-4 h-4" />
|
||||
Compatible with all WireGuard clients
|
||||
{t('siteWgCompatibleAllClients')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<Server className="text-purple-500 w-4 h-4" />
|
||||
Manual configuration required
|
||||
{t('siteWgManualConfigurationRequired')}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -25,7 +25,7 @@ export default function SiteInfoCard({}: SiteInfoCardProps) {
|
|||
} else if (type === "local") {
|
||||
return t('local');
|
||||
} else {
|
||||
return "Unknown";
|
||||
return t('unknown');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ export default function GeneralPage() {
|
|||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
const t = useTranslations();
|
||||
|
||||
const form = useForm<GeneralFormValues>({
|
||||
resolver: zodResolver(GeneralFormSchema),
|
||||
|
@ -56,6 +55,7 @@ export default function GeneralPage() {
|
|||
},
|
||||
mode: "onChange"
|
||||
});
|
||||
const t = useTranslations();
|
||||
|
||||
async function onSubmit(data: GeneralFormValues) {
|
||||
setLoading(true);
|
||||
|
@ -67,16 +67,19 @@ export default function GeneralPage() {
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('siteErrorUpdate'),
|
||||
description: formatAxiosError(e,t('siteErrorUpdateDescription'))
|
||||
title: "Failed to update site",
|
||||
description: formatAxiosError(
|
||||
e,
|
||||
"An error occurred while updating the site."
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
updateSite({ name: data.name });
|
||||
|
||||
toast({
|
||||
title: t('siteUpdated'),
|
||||
description: t('siteUpdatedDescription')
|
||||
title: "Site updated",
|
||||
description: "The site has been updated."
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
|
|
|
@ -70,7 +70,7 @@ const createSiteFormSchema = z
|
|||
.object({
|
||||
name: z
|
||||
.string()
|
||||
.min(2, { message: "Name must be at least 2 characters." })
|
||||
.min(2, "Name must be at least 2 characters.")
|
||||
.max(30, {
|
||||
message: "Name must not be longer than 30 characters."
|
||||
}),
|
||||
|
@ -324,7 +324,7 @@ WantedBy=default.target`
|
|||
};
|
||||
|
||||
const getCommand = () => {
|
||||
const placeholder = ["Unknown command"];
|
||||
const placeholder = [t('unknownCommand')];
|
||||
if (!commands) {
|
||||
return placeholder;
|
||||
}
|
||||
|
@ -381,8 +381,8 @@ WantedBy=default.target`
|
|||
if (!siteDefaults || !wgConfig) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('siteErrorCreate'),
|
||||
description: t('siteErrorCreateKeyPair')
|
||||
title: "Error creating site",
|
||||
description: "Key pair or site defaults not found"
|
||||
});
|
||||
setCreateLoading(false);
|
||||
return;
|
||||
|
@ -399,8 +399,8 @@ WantedBy=default.target`
|
|||
if (!siteDefaults) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('siteErrorCreate'),
|
||||
description: t('siteErrorCreateDefaults')
|
||||
title: "Error creating site",
|
||||
description: "Site defaults not found"
|
||||
});
|
||||
setCreateLoading(false);
|
||||
return;
|
||||
|
@ -422,7 +422,7 @@ WantedBy=default.target`
|
|||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t('siteErrorCreate'),
|
||||
title: "Error creating site",
|
||||
description: formatAxiosError(e)
|
||||
});
|
||||
});
|
||||
|
@ -448,14 +448,14 @@ WantedBy=default.target`
|
|||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch release info: ${response.statusText}`
|
||||
t('newtErrorFetchReleases', {err: response.statusText})
|
||||
);
|
||||
}
|
||||
const data = await response.json();
|
||||
const latestVersion = data.tag_name;
|
||||
newtVersion = latestVersion;
|
||||
} catch (error) {
|
||||
console.error("Error fetching latest release:", error);
|
||||
console.error(t('newtErrorFetchLatest', {err: error instanceof Error ? error.message : String(error)}));
|
||||
}
|
||||
|
||||
const generatedKeypair = generateKeypair();
|
||||
|
@ -612,7 +612,7 @@ WantedBy=default.target`
|
|||
<InfoSections cols={3}>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
Newt Endpoint
|
||||
{t('newtEndpoint')}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<CopyToClipboard
|
||||
|
@ -624,7 +624,7 @@ WantedBy=default.target`
|
|||
</InfoSection>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
Newt ID
|
||||
{t('newtId')}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<CopyToClipboard
|
||||
|
@ -634,7 +634,7 @@ WantedBy=default.target`
|
|||
</InfoSection>
|
||||
<InfoSection>
|
||||
<InfoSectionTitle>
|
||||
Newt Secret Key
|
||||
{t('newtSecretKey')}
|
||||
</InfoSectionTitle>
|
||||
<InfoSectionContent>
|
||||
<CopyToClipboard
|
||||
|
@ -737,8 +737,8 @@ WantedBy=default.target`
|
|||
{["docker", "podman"].includes(
|
||||
platform
|
||||
)
|
||||
? "Method"
|
||||
: "Architecture"}
|
||||
? t('method')
|
||||
: t('architecture')}
|
||||
</p>
|
||||
<div className="grid grid-cols-2 md:grid-cols-5 gap-2">
|
||||
{getArchitectures().map(
|
||||
|
|
|
@ -62,10 +62,10 @@ const createFormSchema = z.object({
|
|||
name: z
|
||||
.string()
|
||||
.min(2, {
|
||||
message: t('apiKeysNameMin')
|
||||
message: t('nameMin', {len: 2})
|
||||
})
|
||||
.max(255, {
|
||||
message: t('apiKeysNameMax')
|
||||
message: t('nameMax', {len: 255})
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
@ -43,9 +43,12 @@ import {
|
|||
import CopyToClipboard from "@app/components/CopyToClipboard";
|
||||
import { Badge } from "@app/components/ui/badge";
|
||||
import { useLicenseStatusContext } from "@app/hooks/useLicenseStatusContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const GeneralFormSchema = z.object({
|
||||
name: z.string().min(2, { message: "Name must be at least 2 characters." }),
|
||||
name: z.string().min(2, { message: t('nameMin', {len: 2}) }),
|
||||
clientId: z.string().min(1, { message: "Client ID is required." }),
|
||||
clientSecret: z.string().min(1, { message: "Client Secret is required." }),
|
||||
authUrl: z.string().url({ message: "Auth URL must be a valid URL." }),
|
||||
|
|
|
@ -37,9 +37,12 @@ import { StrategySelect } from "@app/components/StrategySelect";
|
|||
import { SwitchInput } from "@app/components/SwitchInput";
|
||||
import { Badge } from "@app/components/ui/badge";
|
||||
import { useLicenseStatusContext } from "@app/hooks/useLicenseStatusContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
const createIdpFormSchema = z.object({
|
||||
name: z.string().min(2, { message: "Name must be at least 2 characters." }),
|
||||
name: z.string().min(2, { message: t('nameMin', {len: 2}) }),
|
||||
type: z.enum(["oidc"]),
|
||||
clientId: z.string().min(1, { message: "Client ID is required." }),
|
||||
clientSecret: z.string().min(1, { message: "Client Secret is required." }),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue