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:
vlalx 2025-05-17 18:49:01 +03:00 committed by GitHub
parent 6f54e3da9e
commit 96bfc3cf36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 2749 additions and 590 deletions

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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é."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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>

View file

@ -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}>

View file

@ -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')}

View file

@ -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

View file

@ -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
};
});

View file

@ -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>

View file

@ -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>

View file

@ -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}

View file

@ -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

View file

@ -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>

View file

@ -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}>

View file

@ -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>

View file

@ -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

View file

@ -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>;

View file

@ -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."
});
}

View file

@ -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);

View file

@ -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}`);

View file

@ -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}

View file

@ -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>

View file

@ -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}

View file

@ -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) {

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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);

View file

@ -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>

View file

@ -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')
)
});
});

View file

@ -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 /> */}

View file

@ -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"

View file

@ -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}

View file

@ -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>

View file

@ -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"
});
}

View file

@ -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"

View file

@ -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')}

View file

@ -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>

View file

@ -25,7 +25,7 @@ export default function SiteInfoCard({}: SiteInfoCardProps) {
} else if (type === "local") {
return t('local');
} else {
return "Unknown";
return t('unknown');
}
};

View file

@ -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);

View file

@ -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(

View file

@ -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})
})
});

View file

@ -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." }),

View file

@ -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." }),