merge main
@@ -6,7 +6,9 @@
|
||||
"title": "Konten",
|
||||
"description": "Wählen Sie das Konto aus, das Sie verwenden möchten.",
|
||||
"addAnother": "Ein weiteres Konto hinzufügen",
|
||||
"noResults": "Keine Konten gefunden"
|
||||
"noResults": "Keine Konten gefunden",
|
||||
"verified": "verifiziert",
|
||||
"expired": "abgelaufen"
|
||||
},
|
||||
"logout": {
|
||||
"title": "Logout",
|
||||
@@ -23,14 +25,20 @@
|
||||
"title": "Willkommen zurück!",
|
||||
"description": "Geben Sie Ihre Anmeldedaten ein.",
|
||||
"register": "Neuen Benutzer registrieren",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"loginName": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"verify": {
|
||||
"title": "Passwort",
|
||||
"description": "Geben Sie Ihr Passwort ein.",
|
||||
"resetPassword": "Passwort zurücksetzen",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"password": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Passwort festlegen",
|
||||
@@ -38,12 +46,21 @@
|
||||
"codeSent": "Ein Code wurde an Ihre E-Mail-Adresse gesendet.",
|
||||
"noCodeReceived": "Keinen Code erhalten?",
|
||||
"resend": "Erneut senden",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"code": "Dieses Feld ist erforderlich",
|
||||
"newPassword": "Bitte geben Sie ein Passwort ein!",
|
||||
"confirmPassword": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"title": "Passwort ändern",
|
||||
"description": "Legen Sie das Passwort für Ihr Konto fest",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"newPassword": "Bitte geben Sie ein neues Passwort ein!",
|
||||
"confirmPassword": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
}
|
||||
},
|
||||
"idp": {
|
||||
@@ -85,7 +102,11 @@
|
||||
"description": "Geben Sie Ihre LDAP-Anmeldedaten ein.",
|
||||
"username": "Benutzername",
|
||||
"password": "Passwort",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"username": "Dieses Feld ist erforderlich",
|
||||
"password": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
},
|
||||
"mfa": {
|
||||
"verify": {
|
||||
@@ -107,7 +128,10 @@
|
||||
"emailDescription": "Geben Sie den Code ein, den Sie per E-Mail erhalten haben.",
|
||||
"noCodeReceived": "Keinen Code erhalten?",
|
||||
"resendCode": "Code erneut senden",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"code": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "2-Faktor einrichten",
|
||||
@@ -115,7 +139,10 @@
|
||||
"smsDescription": "Geben Sie Ihre Telefonnummer ein, um einen Code per SMS zu erhalten.",
|
||||
"emailDescription": "Geben Sie Ihre E-Mail-Adresse ein, um einen Code per E-Mail zu erhalten.",
|
||||
"totpRegisterDescription": "Scannen Sie den QR-Code oder navigieren Sie manuell zur URL.",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"code": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkey": {
|
||||
@@ -172,7 +199,16 @@
|
||||
"password": {
|
||||
"title": "Passwort festlegen",
|
||||
"description": "Legen Sie das Passwort für Ihr Konto fest",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"password": "Bitte geben Sie ein Passwort ein!",
|
||||
"confirmPassword": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
},
|
||||
"required": {
|
||||
"firstname": "Dieses Feld ist erforderlich",
|
||||
"lastname": "Dieses Feld ist erforderlich",
|
||||
"email": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
},
|
||||
"invite": {
|
||||
@@ -209,7 +245,10 @@
|
||||
"noCodeReceived": "Keinen Code erhalten?",
|
||||
"resendCode": "Code erneut senden",
|
||||
"codeSent": "Ein Code wurde gerade an Ihre E-Mail-Adresse gesendet.",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"code": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
}
|
||||
},
|
||||
"authenticator": {
|
||||
@@ -223,7 +262,10 @@
|
||||
"usercode": {
|
||||
"title": "Gerätecode",
|
||||
"description": "Geben Sie den Code ein.",
|
||||
"submit": "Weiter"
|
||||
"submit": "Weiter",
|
||||
"required": {
|
||||
"code": "Dieses Feld ist erforderlich"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"title": "{appName} möchte eine Verbindung herstellen:",
|
||||
|
@@ -6,7 +6,9 @@
|
||||
"title": "Accounts",
|
||||
"description": "Select the account you want to use.",
|
||||
"addAnother": "Add another account",
|
||||
"noResults": "No accounts found"
|
||||
"noResults": "No accounts found",
|
||||
"verified": "verified",
|
||||
"expired": "expired"
|
||||
},
|
||||
"logout": {
|
||||
"title": "Logout",
|
||||
@@ -23,14 +25,20 @@
|
||||
"title": "Welcome back!",
|
||||
"description": "Enter your login data.",
|
||||
"register": "Register new user",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"loginName": "This field is required"
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"verify": {
|
||||
"title": "Password",
|
||||
"description": "Enter your password.",
|
||||
"resetPassword": "Reset Password",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"password": "This field is required"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Set Password",
|
||||
@@ -38,12 +46,21 @@
|
||||
"codeSent": "A code has been sent to your email address.",
|
||||
"noCodeReceived": "Didn't receive a code?",
|
||||
"resend": "Resend code",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"code": "This field is required",
|
||||
"newPassword": "You have to provide a password!",
|
||||
"confirmPassword": "This field is required"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"title": "Change Password",
|
||||
"description": "Set the password for your account",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"newPassword": "You have to provide a new password!",
|
||||
"confirmPassword": "This field is required"
|
||||
}
|
||||
}
|
||||
},
|
||||
"idp": {
|
||||
@@ -85,7 +102,11 @@
|
||||
"description": "Enter your LDAP credentials.",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"username": "This field is required",
|
||||
"password": "This field is required"
|
||||
}
|
||||
},
|
||||
"mfa": {
|
||||
"verify": {
|
||||
@@ -107,7 +128,10 @@
|
||||
"emailDescription": "Enter the code you received via email.",
|
||||
"noCodeReceived": "Didn't receive a code?",
|
||||
"resendCode": "Resend code",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"code": "This field is required"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Set up 2-Factor",
|
||||
@@ -115,7 +139,10 @@
|
||||
"smsDescription": "Enter your phone number to receive a code via SMS.",
|
||||
"emailDescription": "Enter your email address to receive a code via email.",
|
||||
"totpRegisterDescription": "Scan the QR Code or navigate to the URL manually.",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"code": "This field is required"
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkey": {
|
||||
@@ -172,7 +199,16 @@
|
||||
"password": {
|
||||
"title": "Set Password",
|
||||
"description": "Set the password for your account",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"password": "You have to provide a password!",
|
||||
"confirmPassword": "This field is required"
|
||||
}
|
||||
},
|
||||
"required": {
|
||||
"firstname": "This field is required",
|
||||
"lastname": "This field is required",
|
||||
"email": "This field is required"
|
||||
}
|
||||
},
|
||||
"invite": {
|
||||
@@ -209,7 +245,10 @@
|
||||
"noCodeReceived": "Didn't receive a code?",
|
||||
"resendCode": "Resend code",
|
||||
"codeSent": "A code has just been sent to your email address.",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"code": "This field is required"
|
||||
}
|
||||
}
|
||||
},
|
||||
"authenticator": {
|
||||
@@ -223,7 +262,10 @@
|
||||
"usercode": {
|
||||
"title": "Device code",
|
||||
"description": "Enter the code displayed on your app or device.",
|
||||
"submit": "Continue"
|
||||
"submit": "Continue",
|
||||
"required": {
|
||||
"code": "This field is required"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"title": "{appName} would like to connect",
|
||||
|
@@ -4,9 +4,11 @@
|
||||
},
|
||||
"accounts": {
|
||||
"title": "Cuentas",
|
||||
"description": "Selecciona la cuenta que deseas usar.",
|
||||
"description": "Seleccione la cuenta que desea utilizar.",
|
||||
"addAnother": "Agregar otra cuenta",
|
||||
"noResults": "No se encontraron cuentas"
|
||||
"noResults": "No se encontraron cuentas",
|
||||
"verified": "verificado",
|
||||
"expired": "expirado"
|
||||
},
|
||||
"logout": {
|
||||
"title": "Cerrar sesión",
|
||||
@@ -23,14 +25,20 @@
|
||||
"title": "¡Bienvenido de nuevo!",
|
||||
"description": "Introduce tus datos de acceso.",
|
||||
"register": "Registrar nuevo usuario",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"loginName": "Este campo es obligatorio"
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"verify": {
|
||||
"title": "Contraseña",
|
||||
"description": "Introduce tu contraseña.",
|
||||
"resetPassword": "Restablecer contraseña",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"password": "Este campo es obligatorio"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Establecer Contraseña",
|
||||
@@ -38,12 +46,21 @@
|
||||
"codeSent": "Se ha enviado un código a su correo electrónico.",
|
||||
"noCodeReceived": "¿No recibiste un código?",
|
||||
"resend": "Reenviar código",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"code": "Este campo es obligatorio",
|
||||
"newPassword": "¡Debes proporcionar una contraseña!",
|
||||
"confirmPassword": "Este campo es obligatorio"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"title": "Cambiar Contraseña",
|
||||
"description": "Establece la contraseña para tu cuenta",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"newPassword": "¡Debes proporcionar una nueva contraseña!",
|
||||
"confirmPassword": "Este campo es obligatorio"
|
||||
}
|
||||
}
|
||||
},
|
||||
"idp": {
|
||||
@@ -85,7 +102,11 @@
|
||||
"description": "Introduce tus credenciales LDAP.",
|
||||
"username": "Nombre de usuario",
|
||||
"password": "Contraseña",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"username": "Este campo es obligatorio",
|
||||
"password": "Este campo es obligatorio"
|
||||
}
|
||||
},
|
||||
"mfa": {
|
||||
"verify": {
|
||||
@@ -107,7 +128,10 @@
|
||||
"emailDescription": "Introduce el código que recibiste por correo electrónico.",
|
||||
"noCodeReceived": "¿No recibiste un código?",
|
||||
"resendCode": "Reenviar código",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"code": "Este campo es obligatorio"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Configurar autenticación de 2 factores",
|
||||
@@ -115,7 +139,10 @@
|
||||
"smsDescription": "Introduce tu número de teléfono para recibir un código por SMS.",
|
||||
"emailDescription": "Introduce tu dirección de correo electrónico para recibir un código por correo electrónico.",
|
||||
"totpRegisterDescription": "Escanea el código QR o navega manualmente a la URL.",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"code": "Este campo es obligatorio"
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkey": {
|
||||
@@ -172,7 +199,16 @@
|
||||
"password": {
|
||||
"title": "Establecer Contraseña",
|
||||
"description": "Establece la contraseña para tu cuenta",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"password": "¡Debes proporcionar una contraseña!",
|
||||
"confirmPassword": "Este campo es obligatorio"
|
||||
}
|
||||
},
|
||||
"required": {
|
||||
"firstname": "Este campo es obligatorio",
|
||||
"lastname": "Este campo es obligatorio",
|
||||
"email": "Este campo es obligatorio"
|
||||
}
|
||||
},
|
||||
"invite": {
|
||||
@@ -209,7 +245,10 @@
|
||||
"noCodeReceived": "¿No recibiste un código?",
|
||||
"resendCode": "Reenviar código",
|
||||
"codeSent": "Se ha enviado un código a tu dirección de correo electrónico.",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"code": "Este campo es obligatorio"
|
||||
}
|
||||
}
|
||||
},
|
||||
"authenticator": {
|
||||
@@ -223,7 +262,10 @@
|
||||
"usercode": {
|
||||
"title": "Código del dispositivo",
|
||||
"description": "Introduce el código.",
|
||||
"submit": "Continuar"
|
||||
"submit": "Continuar",
|
||||
"required": {
|
||||
"code": "Este campo es obligatorio"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"title": "{appName} desea conectarse:",
|
||||
|
@@ -4,9 +4,11 @@
|
||||
},
|
||||
"accounts": {
|
||||
"title": "Account",
|
||||
"description": "Seleziona l'account che desideri utilizzare.",
|
||||
"description": "Seleziona l'account che vuoi utilizzare.",
|
||||
"addAnother": "Aggiungi un altro account",
|
||||
"noResults": "Nessun account trovato"
|
||||
"noResults": "Nessun account trovato",
|
||||
"verified": "verificato",
|
||||
"expired": "scaduto"
|
||||
},
|
||||
"logout": {
|
||||
"title": "Esci",
|
||||
@@ -23,14 +25,20 @@
|
||||
"title": "Bentornato!",
|
||||
"description": "Inserisci i tuoi dati di accesso.",
|
||||
"register": "Registrati come nuovo utente",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"loginName": "Questo campo è obbligatorio"
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"verify": {
|
||||
"title": "Password",
|
||||
"description": "Inserisci la tua password.",
|
||||
"resetPassword": "Reimposta Password",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"password": "Questo campo è obbligatorio"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Imposta Password",
|
||||
@@ -38,12 +46,21 @@
|
||||
"codeSent": "Un codice è stato inviato al tuo indirizzo email.",
|
||||
"noCodeReceived": "Non hai ricevuto un codice?",
|
||||
"resend": "Invia di nuovo",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"code": "Questo campo è obbligatorio",
|
||||
"newPassword": "Devi fornire una password!",
|
||||
"confirmPassword": "Questo campo è obbligatorio"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"title": "Cambia Password",
|
||||
"description": "Imposta la password per il tuo account",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"newPassword": "Devi fornire una nuova password!",
|
||||
"confirmPassword": "Questo campo è obbligatorio"
|
||||
}
|
||||
}
|
||||
},
|
||||
"idp": {
|
||||
@@ -85,7 +102,11 @@
|
||||
"description": "Inserisci le tue credenziali LDAP.",
|
||||
"username": "Nome utente",
|
||||
"password": "Password",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"username": "Questo campo è obbligatorio",
|
||||
"password": "Questo campo è obbligatorio"
|
||||
}
|
||||
},
|
||||
"mfa": {
|
||||
"verify": {
|
||||
@@ -107,7 +128,10 @@
|
||||
"emailDescription": "Inserisci il codice ricevuto via email.",
|
||||
"noCodeReceived": "Non hai ricevuto un codice?",
|
||||
"resendCode": "Invia di nuovo il codice",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"code": "Questo campo è obbligatorio"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Configura l'autenticazione a 2 fattori",
|
||||
@@ -115,7 +139,10 @@
|
||||
"smsDescription": "Inserisci il tuo numero di telefono per ricevere un codice via SMS.",
|
||||
"emailDescription": "Inserisci il tuo indirizzo email per ricevere un codice via email.",
|
||||
"totpRegisterDescription": "Scansiona il codice QR o naviga manualmente all'URL.",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"code": "Questo campo è obbligatorio"
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkey": {
|
||||
@@ -172,7 +199,16 @@
|
||||
"password": {
|
||||
"title": "Imposta Password",
|
||||
"description": "Imposta la password per il tuo account",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"password": "Devi fornire una password!",
|
||||
"confirmPassword": "Questo campo è obbligatorio"
|
||||
}
|
||||
},
|
||||
"required": {
|
||||
"firstname": "Questo campo è obbligatorio",
|
||||
"lastname": "Questo campo è obbligatorio",
|
||||
"email": "Questo campo è obbligatorio"
|
||||
}
|
||||
},
|
||||
"invite": {
|
||||
@@ -209,7 +245,10 @@
|
||||
"noCodeReceived": "Non hai ricevuto un codice?",
|
||||
"resendCode": "Invia di nuovo il codice",
|
||||
"codeSent": "Un codice è stato appena inviato al tuo indirizzo email.",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"code": "Questo campo è obbligatorio"
|
||||
}
|
||||
}
|
||||
},
|
||||
"authenticator": {
|
||||
@@ -223,7 +262,10 @@
|
||||
"usercode": {
|
||||
"title": "Codice dispositivo",
|
||||
"description": "Inserisci il codice.",
|
||||
"submit": "Continua"
|
||||
"submit": "Continua",
|
||||
"required": {
|
||||
"code": "Questo campo è obbligatorio"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"title": "{appName} desidera connettersi:",
|
||||
|
@@ -6,7 +6,9 @@
|
||||
"title": "Konta",
|
||||
"description": "Wybierz konto, którego chcesz użyć.",
|
||||
"addAnother": "Dodaj kolejne konto",
|
||||
"noResults": "Nie znaleziono kont"
|
||||
"noResults": "Nie znaleziono kont",
|
||||
"verified": "zweryfikowany",
|
||||
"expired": "wygasł"
|
||||
},
|
||||
"logout": {
|
||||
"title": "Wyloguj się",
|
||||
@@ -23,14 +25,20 @@
|
||||
"title": "Witamy ponownie!",
|
||||
"description": "Wprowadź dane logowania.",
|
||||
"register": "Zarejestruj nowego użytkownika",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"loginName": "To pole jest wymagane"
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"verify": {
|
||||
"title": "Hasło",
|
||||
"description": "Wprowadź swoje hasło.",
|
||||
"resetPassword": "Zresetuj hasło",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"password": "To pole jest wymagane"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Ustaw hasło",
|
||||
@@ -38,12 +46,21 @@
|
||||
"codeSent": "Kod został wysłany na twój adres e-mail.",
|
||||
"noCodeReceived": "Nie otrzymałeś kodu?",
|
||||
"resend": "Wyślij kod ponownie",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"code": "To pole jest wymagane",
|
||||
"newPassword": "Musisz podać hasło!",
|
||||
"confirmPassword": "To pole jest wymagane"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"title": "Zmień hasło",
|
||||
"description": "Ustaw nowe hasło dla swojego konta",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"newPassword": "Musisz podać nowe hasło!",
|
||||
"confirmPassword": "To pole jest wymagane"
|
||||
}
|
||||
}
|
||||
},
|
||||
"idp": {
|
||||
@@ -85,7 +102,11 @@
|
||||
"description": "Wprowadź swoje dane logowania LDAP.",
|
||||
"username": "Nazwa użytkownika",
|
||||
"password": "Hasło",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"username": "To pole jest wymagane",
|
||||
"password": "To pole jest wymagane"
|
||||
}
|
||||
},
|
||||
"mfa": {
|
||||
"verify": {
|
||||
@@ -107,7 +128,10 @@
|
||||
"emailDescription": "Wprowadź kod otrzymany e-mailem.",
|
||||
"noCodeReceived": "Nie otrzymałeś kodu?",
|
||||
"resendCode": "Wyślij kod ponownie",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"code": "To pole jest wymagane"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Skonfiguruj uwierzytelnianie dwuskładnikowe",
|
||||
@@ -115,7 +139,10 @@
|
||||
"smsDescription": "Wprowadź swój numer telefonu, aby otrzymać kod SMS-em.",
|
||||
"emailDescription": "Wprowadź swój adres e-mail, aby otrzymać kod e-mailem.",
|
||||
"totpRegisterDescription": "Zeskanuj kod QR lub otwórz adres URL ręcznie.",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"code": "To pole jest wymagane"
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkey": {
|
||||
@@ -172,7 +199,16 @@
|
||||
"password": {
|
||||
"title": "Ustaw hasło",
|
||||
"description": "Ustaw hasło dla swojego konta",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"password": "Musisz podać hasło!",
|
||||
"confirmPassword": "To pole jest wymagane"
|
||||
}
|
||||
},
|
||||
"required": {
|
||||
"firstname": "To pole jest wymagane",
|
||||
"lastname": "To pole jest wymagane",
|
||||
"email": "To pole jest wymagane"
|
||||
}
|
||||
},
|
||||
"invite": {
|
||||
@@ -209,7 +245,10 @@
|
||||
"noCodeReceived": "Nie otrzymałeś kodu?",
|
||||
"resendCode": "Wyślij kod ponownie",
|
||||
"codeSent": "Kod został właśnie wysłany na twój adres e-mail.",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"code": "To pole jest wymagane"
|
||||
}
|
||||
}
|
||||
},
|
||||
"authenticator": {
|
||||
@@ -223,7 +262,10 @@
|
||||
"usercode": {
|
||||
"title": "Kod urządzenia",
|
||||
"description": "Wprowadź kod.",
|
||||
"submit": "Kontynuuj"
|
||||
"submit": "Kontynuuj",
|
||||
"required": {
|
||||
"code": "To pole jest wymagane"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"title": "{appName} chce się połączyć:",
|
||||
|
@@ -6,7 +6,9 @@
|
||||
"title": "Аккаунты",
|
||||
"description": "Выберите аккаунт, который хотите использовать.",
|
||||
"addAnother": "Добавить другой аккаунт",
|
||||
"noResults": "Аккаунты не найдены"
|
||||
"noResults": "Аккаунты не найдены",
|
||||
"verified": "проверенный",
|
||||
"expired": "истёк"
|
||||
},
|
||||
"logout": {
|
||||
"title": "Выход",
|
||||
@@ -23,14 +25,20 @@
|
||||
"title": "С возвращением!",
|
||||
"description": "Введите свои данные для входа.",
|
||||
"register": "Зарегистрировать нового пользователя",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"loginName": "Это поле обязательно для заполнения"
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"verify": {
|
||||
"title": "Пароль",
|
||||
"description": "Введите ваш пароль.",
|
||||
"resetPassword": "Сбросить пароль",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"password": "Это поле обязательно для заполнения"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Установить пароль",
|
||||
@@ -38,12 +46,21 @@
|
||||
"codeSent": "Код отправлен на ваш адрес электронной почты.",
|
||||
"noCodeReceived": "Не получили код?",
|
||||
"resend": "Отправить код повторно",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"code": "Это поле обязательно для заполнения",
|
||||
"newPassword": "Вы должны указать пароль!",
|
||||
"confirmPassword": "Это поле обязательно для заполнения"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"title": "Изменить пароль",
|
||||
"description": "Установите пароль для вашего аккаунта",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"newPassword": "Вы должны указать новый пароль!",
|
||||
"confirmPassword": "Это поле обязательно для заполнения"
|
||||
}
|
||||
}
|
||||
},
|
||||
"idp": {
|
||||
@@ -85,7 +102,11 @@
|
||||
"description": "Введите ваши учетные данные LDAP.",
|
||||
"username": "Имя пользователя",
|
||||
"password": "Пароль",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"username": "Это поле обязательно для заполнения",
|
||||
"password": "Это поле обязательно для заполнения"
|
||||
}
|
||||
},
|
||||
"mfa": {
|
||||
"verify": {
|
||||
@@ -107,7 +128,10 @@
|
||||
"emailDescription": "Введите код, полученный по email.",
|
||||
"noCodeReceived": "Не получили код?",
|
||||
"resendCode": "Отправить код повторно",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"code": "Это поле обязательно для заполнения"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "Настройка двухфакторной аутентификации",
|
||||
@@ -115,7 +139,10 @@
|
||||
"smsDescription": "Введите номер телефона для получения кода по SMS.",
|
||||
"emailDescription": "Введите email для получения кода.",
|
||||
"totpRegisterDescription": "Отсканируйте QR-код или перейдите по ссылке вручную.",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"code": "Это поле обязательно для заполнения"
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkey": {
|
||||
@@ -172,7 +199,16 @@
|
||||
"password": {
|
||||
"title": "Установить пароль",
|
||||
"description": "Установите пароль для вашего аккаунта",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"password": "Вы должны указать пароль!",
|
||||
"confirmPassword": "Это поле обязательно для заполнения"
|
||||
}
|
||||
},
|
||||
"required": {
|
||||
"firstname": "Это поле обязательно для заполнения",
|
||||
"lastname": "Это поле обязательно для заполнения",
|
||||
"email": "Это поле обязательно для заполнения"
|
||||
}
|
||||
},
|
||||
"invite": {
|
||||
@@ -209,7 +245,10 @@
|
||||
"noCodeReceived": "Не получили код?",
|
||||
"resendCode": "Отправить код повторно",
|
||||
"codeSent": "Код отправлен на ваш email.",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"code": "Это поле обязательно для заполнения"
|
||||
}
|
||||
}
|
||||
},
|
||||
"authenticator": {
|
||||
@@ -223,7 +262,10 @@
|
||||
"usercode": {
|
||||
"title": "Код устройства",
|
||||
"description": "Введите код.",
|
||||
"submit": "Продолжить"
|
||||
"submit": "Продолжить",
|
||||
"required": {
|
||||
"code": "Это поле обязательно для заполнения"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"title": "{appName} хочет подключиться:",
|
||||
|
@@ -4,9 +4,11 @@
|
||||
},
|
||||
"accounts": {
|
||||
"title": "账户",
|
||||
"description": "选择您想使用的账户。",
|
||||
"description": "选择您要使用的账户。",
|
||||
"addAnother": "添加另一个账户",
|
||||
"noResults": "未找到账户"
|
||||
"noResults": "未找到账户",
|
||||
"verified": "已验证",
|
||||
"expired": "已过期"
|
||||
},
|
||||
"logout": {
|
||||
"title": "注销",
|
||||
@@ -23,14 +25,20 @@
|
||||
"title": "欢迎回来!",
|
||||
"description": "请输入您的登录信息。",
|
||||
"register": "注册新用户",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"loginName": "此字段为必填项"
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"verify": {
|
||||
"title": "密码",
|
||||
"description": "请输入您的密码。",
|
||||
"resetPassword": "重置密码",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"password": "此字段为必填项"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "设置密码",
|
||||
@@ -38,12 +46,21 @@
|
||||
"codeSent": "验证码已发送到您的邮箱。",
|
||||
"noCodeReceived": "没有收到验证码?",
|
||||
"resend": "重发验证码",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"code": "此字段为必填项",
|
||||
"newPassword": "必须提供密码!",
|
||||
"confirmPassword": "此字段为必填项"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"title": "更改密码",
|
||||
"description": "为您的账户设置密码",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"newPassword": "必须提供新密码!",
|
||||
"confirmPassword": "此字段为必填项"
|
||||
}
|
||||
}
|
||||
},
|
||||
"idp": {
|
||||
@@ -85,7 +102,11 @@
|
||||
"description": "请输入您的 LDAP 凭据。",
|
||||
"username": "用户名",
|
||||
"password": "密码",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"username": "此字段为必填项",
|
||||
"password": "此字段为必填项"
|
||||
}
|
||||
},
|
||||
"mfa": {
|
||||
"verify": {
|
||||
@@ -107,7 +128,10 @@
|
||||
"emailDescription": "输入通过电子邮件收到的验证码。",
|
||||
"noCodeReceived": "没有收到验证码?",
|
||||
"resendCode": "重发验证码",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"code": "此字段为必填项"
|
||||
}
|
||||
},
|
||||
"set": {
|
||||
"title": "设置双因素认证",
|
||||
@@ -115,7 +139,10 @@
|
||||
"smsDescription": "输入您的电话号码以接收短信验证码。",
|
||||
"emailDescription": "输入您的电子邮箱地址以接收电子邮件验证码。",
|
||||
"totpRegisterDescription": "扫描二维码或手动导航到URL。",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"code": "此字段为必填项"
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkey": {
|
||||
@@ -172,7 +199,16 @@
|
||||
"password": {
|
||||
"title": "设置密码",
|
||||
"description": "为您的账户设置密码",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"password": "必须提供密码!",
|
||||
"confirmPassword": "此字段为必填项"
|
||||
}
|
||||
},
|
||||
"required": {
|
||||
"firstname": "此字段为必填项",
|
||||
"lastname": "此字段为必填项",
|
||||
"email": "此字段为必填项"
|
||||
}
|
||||
},
|
||||
"invite": {
|
||||
@@ -209,7 +245,10 @@
|
||||
"noCodeReceived": "没有收到验证码?",
|
||||
"resendCode": "重发验证码",
|
||||
"codeSent": "刚刚发送了一封包含验证码的电子邮件。",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"code": "此字段为必填项"
|
||||
}
|
||||
}
|
||||
},
|
||||
"authenticator": {
|
||||
@@ -223,7 +262,10 @@
|
||||
"usercode": {
|
||||
"title": "设备代码",
|
||||
"description": "输入代码。",
|
||||
"submit": "继续"
|
||||
"submit": "继续",
|
||||
"required": {
|
||||
"code": "此字段为必填项"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"title": "{appName} 想要连接:",
|
||||
|
@@ -25,6 +25,7 @@
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^2.1.9",
|
||||
"@heroicons/react": "2.1.3",
|
||||
"@radix-ui/react-tooltip": "^1.2.7",
|
||||
"@tailwindcss/forms": "0.5.7",
|
||||
"@vercel/analytics": "^1.2.2",
|
||||
"@zitadel/client": "latest",
|
||||
|
@@ -15,12 +15,12 @@ import { headers } from "next/headers";
|
||||
import Link from "next/link";
|
||||
|
||||
async function loadSessions({ serviceUrl }: { serviceUrl: string }) {
|
||||
const ids: (string | undefined)[] = await getAllSessionCookieIds();
|
||||
const cookieIds = await getAllSessionCookieIds();
|
||||
|
||||
if (ids && ids.length) {
|
||||
if (cookieIds && cookieIds.length) {
|
||||
const response = await listSessions({
|
||||
serviceUrl,
|
||||
ids: ids.filter((id) => !!id) as string[],
|
||||
ids: cookieIds.filter((id) => !!id) as string[],
|
||||
});
|
||||
return response?.sessions ?? [];
|
||||
} else {
|
||||
|
@@ -5,6 +5,7 @@ import { LanguageSwitcher } from "@/components/language-switcher";
|
||||
import { Skeleton } from "@/components/skeleton";
|
||||
import { Theme } from "@/components/theme";
|
||||
import { ThemeProvider } from "@/components/theme-provider";
|
||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||
import { Analytics } from "@vercel/analytics/react";
|
||||
import { Lato } from "next/font/google";
|
||||
import { ReactNode, Suspense } from "react";
|
||||
@@ -24,36 +25,38 @@ export default async function RootLayout({
|
||||
<head />
|
||||
<body>
|
||||
<ThemeProvider>
|
||||
<Suspense
|
||||
fallback={
|
||||
<div
|
||||
className={`relative flex min-h-screen flex-col justify-center bg-background-light-600 dark:bg-background-dark-600`}
|
||||
>
|
||||
<div className="relative mx-auto w-full max-w-[440px] py-8">
|
||||
<Skeleton>
|
||||
<div className="h-40"></div>
|
||||
</Skeleton>
|
||||
<div className="flex flex-row items-center justify-end space-x-4 py-4">
|
||||
<Theme />
|
||||
<Tooltip.Provider>
|
||||
<Suspense
|
||||
fallback={
|
||||
<div
|
||||
className={`relative flex min-h-screen flex-col justify-center bg-background-light-600 dark:bg-background-dark-600`}
|
||||
>
|
||||
<div className="relative mx-auto w-full max-w-[440px] py-8">
|
||||
<Skeleton>
|
||||
<div className="h-40"></div>
|
||||
</Skeleton>
|
||||
<div className="flex flex-row items-center justify-end space-x-4 py-4">
|
||||
<Theme />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<LanguageProvider>
|
||||
<div
|
||||
className={`relative flex min-h-screen flex-col justify-center bg-background-light-600 dark:bg-background-dark-600`}
|
||||
>
|
||||
<div className="relative mx-auto w-full max-w-[440px] py-8">
|
||||
{children}
|
||||
<div className="flex flex-row items-center justify-end space-x-4 py-4">
|
||||
<LanguageSwitcher />
|
||||
<Theme />
|
||||
}
|
||||
>
|
||||
<LanguageProvider>
|
||||
<div
|
||||
className={`relative flex min-h-screen flex-col justify-center bg-background-light-600 dark:bg-background-dark-600`}
|
||||
>
|
||||
<div className="relative mx-auto w-full max-w-[440px] py-8">
|
||||
{children}
|
||||
<div className="flex flex-row items-center justify-end space-x-4 py-4">
|
||||
<LanguageSwitcher />
|
||||
<Theme />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LanguageProvider>
|
||||
</Suspense>
|
||||
</LanguageProvider>
|
||||
</Suspense>
|
||||
</Tooltip.Provider>
|
||||
</ThemeProvider>
|
||||
<Analytics />
|
||||
</body>
|
||||
|
@@ -12,12 +12,12 @@ import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||
import { headers } from "next/headers";
|
||||
|
||||
async function loadSessions({ serviceUrl }: { serviceUrl: string }) {
|
||||
const ids: (string | undefined)[] = await getAllSessionCookieIds();
|
||||
const cookieIds = await getAllSessionCookieIds();
|
||||
|
||||
if (ids && ids.length) {
|
||||
if (cookieIds && cookieIds.length) {
|
||||
const response = await listSessions({
|
||||
serviceUrl,
|
||||
ids: ids.filter((id) => !!id) as string[],
|
||||
ids: cookieIds.filter((id) => !!id) as string[],
|
||||
});
|
||||
return response?.sessions ?? [];
|
||||
} else {
|
||||
|
@@ -39,17 +39,13 @@ export default async function Page(props: {
|
||||
const { method } = params;
|
||||
|
||||
const session = sessionId
|
||||
? await loadSessionById(serviceUrl, sessionId, organization)
|
||||
? await loadSessionById(sessionId, organization)
|
||||
: await loadMostRecentSession({
|
||||
serviceUrl,
|
||||
sessionParams: { loginName, organization },
|
||||
});
|
||||
|
||||
async function loadSessionById(
|
||||
host: string,
|
||||
sessionId: string,
|
||||
organization?: string,
|
||||
) {
|
||||
async function loadSessionById(sessionId: string, organization?: string) {
|
||||
const recent = await getSessionCookieById({ sessionId, organization });
|
||||
return getSession({
|
||||
serviceUrl,
|
||||
|
@@ -66,7 +66,6 @@ export default async function Page(props: {
|
||||
error = err;
|
||||
});
|
||||
} else if (method === "sms") {
|
||||
// does not work
|
||||
await addOTPSMS({
|
||||
serviceUrl,
|
||||
userId: session.factors.user.id,
|
||||
@@ -75,7 +74,6 @@ export default async function Page(props: {
|
||||
new Error("Could not add OTP via SMS");
|
||||
});
|
||||
} else if (method === "email") {
|
||||
// works
|
||||
await addOTPEmail({
|
||||
serviceUrl,
|
||||
userId: session.factors.user.id,
|
||||
@@ -108,6 +106,7 @@ export default async function Page(props: {
|
||||
paramsToContinue.append("requestId", requestId);
|
||||
}
|
||||
urlToContinue = `/otp/${method}?` + paramsToContinue;
|
||||
|
||||
// immediately check the OTP on the next page if sms or email was set up
|
||||
if (["email", "sms"].includes(method)) {
|
||||
return redirect(urlToContinue);
|
||||
|
@@ -15,6 +15,7 @@ import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_
|
||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { FieldValues, useForm } from "react-hook-form";
|
||||
import { Alert } from "./alert";
|
||||
import { BackButton } from "./back-button";
|
||||
@@ -56,6 +57,8 @@ export function ChangePasswordForm({
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("password");
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
@@ -156,7 +159,7 @@ export function ChangePasswordForm({
|
||||
autoComplete="new-password"
|
||||
required
|
||||
{...register("password", {
|
||||
required: "You have to provide a new password!",
|
||||
required: t("change.required.newPassword"),
|
||||
})}
|
||||
label="New Password"
|
||||
error={errors.password?.message as string}
|
||||
@@ -169,7 +172,7 @@ export function ChangePasswordForm({
|
||||
required
|
||||
autoComplete="new-password"
|
||||
{...register("confirmPassword", {
|
||||
required: "This field is required",
|
||||
required: t("change.required.confirmPassword"),
|
||||
})}
|
||||
label="Confirm Password"
|
||||
error={errors.confirmPassword?.message as string}
|
||||
|
@@ -4,6 +4,7 @@ import { Alert } from "@/components/alert";
|
||||
import { getDeviceAuthorizationRequest } from "@/lib/server/oidc";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { BackButton } from "./back-button";
|
||||
import { Button, ButtonVariants } from "./button";
|
||||
@@ -25,6 +26,8 @@ export function DeviceCodeForm({ userCode }: { userCode?: string }) {
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("device");
|
||||
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
@@ -62,7 +65,7 @@ export function DeviceCodeForm({ userCode }: { userCode?: string }) {
|
||||
<TextInput
|
||||
type="text"
|
||||
autoComplete="one-time-code"
|
||||
{...register("userCode", { required: "This field is required" })}
|
||||
{...register("userCode", { required: t("usercode.required.code") })}
|
||||
label="Code"
|
||||
data-testid="code-text-input"
|
||||
/>
|
||||
|
@@ -68,7 +68,7 @@ export function LDAPUsernamePasswordForm({ idpId, link }: Props) {
|
||||
<TextInput
|
||||
type="text"
|
||||
autoComplete="username"
|
||||
{...register("loginName", { required: "This field is required" })}
|
||||
{...register("loginName", { required: t("required.username") })}
|
||||
label={t("username")}
|
||||
data-testid="username-text-input"
|
||||
/>
|
||||
@@ -77,7 +77,7 @@ export function LDAPUsernamePasswordForm({ idpId, link }: Props) {
|
||||
<TextInput
|
||||
type="password"
|
||||
autoComplete="password"
|
||||
{...register("password", { required: "This field is required" })}
|
||||
{...register("password", { required: t("required.password") })}
|
||||
label={t("password")}
|
||||
data-testid="password-text-input"
|
||||
/>
|
||||
|
@@ -11,6 +11,7 @@ import { useEffect, useRef, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { Alert, AlertType } from "./alert";
|
||||
import { BackButton } from "./back-button";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Button, ButtonVariants } from "./button";
|
||||
import { TextInput } from "./input";
|
||||
import { Spinner } from "./spinner";
|
||||
@@ -42,6 +43,8 @@ export function LoginOTP({
|
||||
code,
|
||||
loginSettings,
|
||||
}: Props) {
|
||||
const t = useTranslations("otp");
|
||||
|
||||
const [error, setError] = useState<string>("");
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
|
||||
@@ -249,7 +252,7 @@ export function LoginOTP({
|
||||
<div className="mt-4">
|
||||
<TextInput
|
||||
type="text"
|
||||
{...register("code", { required: "This field is required" })}
|
||||
{...register("code", { required: t("verify.required.code") })}
|
||||
label="Code"
|
||||
autoComplete="one-time-code"
|
||||
data-testid="code-text-input"
|
||||
|
@@ -6,6 +6,7 @@ import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_
|
||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { Alert, AlertType } from "./alert";
|
||||
import { BackButton } from "./back-button";
|
||||
@@ -34,6 +35,8 @@ export function PasswordForm({
|
||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||
mode: "onBlur",
|
||||
});
|
||||
|
||||
const t = useTranslations("password");
|
||||
|
||||
const [info, setInfo] = useState<string>("");
|
||||
const [error, setError] = useState<string>("");
|
||||
@@ -118,7 +121,7 @@ export function PasswordForm({
|
||||
<TextInput
|
||||
type="password"
|
||||
autoComplete="password"
|
||||
{...register("password", { required: "This field is required" })}
|
||||
{...register("password", { required: t("verify.required.password") })}
|
||||
label="Password"
|
||||
data-testid="password-text-input"
|
||||
/>
|
||||
|
@@ -3,6 +3,7 @@
|
||||
import { registerUserAndLinkToIDP } from "@/lib/server/register";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { FieldValues, useForm } from "react-hook-form";
|
||||
import { Alert } from "./alert";
|
||||
import { BackButton } from "./back-button";
|
||||
@@ -54,6 +55,8 @@ export function RegisterFormIDPIncomplete({
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("register");
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
@@ -102,7 +105,7 @@ export function RegisterFormIDPIncomplete({
|
||||
type="firstname"
|
||||
autoComplete="firstname"
|
||||
required
|
||||
{...register("firstname", { required: "This field is required" })}
|
||||
{...register("firstname", { required: t("required.firstname") })}
|
||||
label="First name"
|
||||
error={errors.firstname?.message as string}
|
||||
data-testid="firstname-text-input"
|
||||
@@ -113,7 +116,7 @@ export function RegisterFormIDPIncomplete({
|
||||
type="lastname"
|
||||
autoComplete="lastname"
|
||||
required
|
||||
{...register("lastname", { required: "This field is required" })}
|
||||
{...register("lastname", { required: t("required.lastname") })}
|
||||
label="Last name"
|
||||
error={errors.lastname?.message as string}
|
||||
data-testid="lastname-text-input"
|
||||
@@ -124,7 +127,7 @@ export function RegisterFormIDPIncomplete({
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
required
|
||||
{...register("email", { required: "This field is required" })}
|
||||
{...register("email", { required: t("required.email") })}
|
||||
label="E-mail"
|
||||
error={errors.email?.message as string}
|
||||
data-testid="email-text-input"
|
||||
|
@@ -8,6 +8,7 @@ import {
|
||||
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { FieldValues, useForm } from "react-hook-form";
|
||||
import { Alert, AlertType } from "./alert";
|
||||
import {
|
||||
@@ -60,6 +61,8 @@ export function RegisterForm({
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("register");
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [selected, setSelected] = useState<AuthenticationMethod>(methods[0]);
|
||||
const [error, setError] = useState<string>("");
|
||||
@@ -130,7 +133,7 @@ export function RegisterForm({
|
||||
type="firstname"
|
||||
autoComplete="firstname"
|
||||
required
|
||||
{...register("firstname", { required: "This field is required" })}
|
||||
{...register("firstname", { required: t("required.firstname") })}
|
||||
label="First name"
|
||||
error={errors.firstname?.message as string}
|
||||
data-testid="firstname-text-input"
|
||||
@@ -141,7 +144,7 @@ export function RegisterForm({
|
||||
type="lastname"
|
||||
autoComplete="lastname"
|
||||
required
|
||||
{...register("lastname", { required: "This field is required" })}
|
||||
{...register("lastname", { required: t("required.lastname") })}
|
||||
label="Last name"
|
||||
error={errors.lastname?.message as string}
|
||||
data-testid="lastname-text-input"
|
||||
@@ -152,7 +155,7 @@ export function RegisterForm({
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
required
|
||||
{...register("email", { required: "This field is required" })}
|
||||
{...register("email", { required: t("required.email") })}
|
||||
label="E-mail"
|
||||
error={errors.email?.message as string}
|
||||
data-testid="email-text-input"
|
||||
|
@@ -3,6 +3,7 @@
|
||||
import { sendLoginname } from "@/lib/server/loginname";
|
||||
import { clearSession, continueWithSession } from "@/lib/server/session";
|
||||
import { XCircleIcon } from "@heroicons/react/24/outline";
|
||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||
import { Timestamp, timestampDate } from "@zitadel/client";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||
import moment from "moment";
|
||||
@@ -10,6 +11,7 @@ import { useLocale } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { Avatar } from "./avatar";
|
||||
import { Translated } from "./translated";
|
||||
|
||||
export function isSessionValid(session: Partial<Session>): {
|
||||
valid: boolean;
|
||||
@@ -66,91 +68,107 @@ export function SessionItem({
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (valid && session?.factors?.user) {
|
||||
const resp = await continueWithSession({
|
||||
...session,
|
||||
requestId: requestId,
|
||||
});
|
||||
<Tooltip.Root delayDuration={300}>
|
||||
<Tooltip.Trigger asChild>
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (valid && session?.factors?.user) {
|
||||
const resp = await continueWithSession({
|
||||
...session,
|
||||
requestId: requestId,
|
||||
});
|
||||
|
||||
if (resp?.redirect) {
|
||||
return router.push(resp.redirect);
|
||||
}
|
||||
} else if (session.factors?.user) {
|
||||
setLoading(true);
|
||||
const res = await sendLoginname({
|
||||
loginName: session.factors?.user?.loginName,
|
||||
organization: session.factors.user.organizationId,
|
||||
requestId: requestId,
|
||||
})
|
||||
.catch(() => {
|
||||
setError("An internal error occurred");
|
||||
return;
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
if (resp?.redirect) {
|
||||
return router.push(resp.redirect);
|
||||
}
|
||||
} else if (session.factors?.user) {
|
||||
setLoading(true);
|
||||
const res = await sendLoginname({
|
||||
loginName: session.factors?.user?.loginName,
|
||||
organization: session.factors.user.organizationId,
|
||||
requestId: requestId,
|
||||
})
|
||||
.catch(() => {
|
||||
setError("An internal error occurred");
|
||||
return;
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
if (res && "redirect" in res && res.redirect) {
|
||||
return router.push(res.redirect);
|
||||
}
|
||||
if (res && "redirect" in res && res.redirect) {
|
||||
return router.push(res.redirect);
|
||||
}
|
||||
|
||||
if (res && "error" in res && res.error) {
|
||||
setError(res.error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}}
|
||||
className="group flex flex-row items-center rounded-md border border-divider-light bg-background-light-400 px-4 py-2 transition-all hover:shadow-lg dark:bg-background-dark-400 dark:hover:bg-white/10"
|
||||
>
|
||||
<div className="pr-4">
|
||||
<Avatar
|
||||
size="small"
|
||||
loginName={session.factors?.user?.loginName as string}
|
||||
name={session.factors?.user?.displayName ?? ""}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-start overflow-hidden">
|
||||
<span className="">{session.factors?.user?.displayName}</span>
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
{session.factors?.user?.loginName}
|
||||
</span>
|
||||
{valid ? (
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
{verifiedAt && moment(timestampDate(verifiedAt)).fromNow()}
|
||||
</span>
|
||||
) : (
|
||||
verifiedAt && (
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
expired{" "}
|
||||
{session.expirationDate &&
|
||||
moment(timestampDate(session.expirationDate)).fromNow()}
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
|
||||
<span className="flex-grow"></span>
|
||||
<div className="relative flex flex-row items-center">
|
||||
{valid ? (
|
||||
<div className="absolute right-0 mx-2 h-2 w-2 transform rounded-full bg-green-500 transition-all group-hover:right-6"></div>
|
||||
) : (
|
||||
<div className="absolute right-0 mx-2 h-2 w-2 transform rounded-full bg-red-500 transition-all group-hover:right-6"></div>
|
||||
)}
|
||||
|
||||
<XCircleIcon
|
||||
className="hidden h-5 w-5 opacity-50 transition-all hover:opacity-100 group-hover:block"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
clearSessionId(session.id).then(() => {
|
||||
reload();
|
||||
});
|
||||
if (res && "error" in res && res.error) {
|
||||
setError(res.error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
className="group flex flex-row items-center rounded-md border border-divider-light bg-background-light-400 px-4 py-2 transition-all hover:shadow-lg dark:bg-background-dark-400 dark:hover:bg-white/10"
|
||||
>
|
||||
<div className="pr-4">
|
||||
<Avatar
|
||||
size="small"
|
||||
loginName={session.factors?.user?.loginName as string}
|
||||
name={session.factors?.user?.displayName ?? ""}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-start overflow-hidden">
|
||||
<span className="">{session.factors?.user?.displayName}</span>
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
{session.factors?.user?.loginName}
|
||||
</span>
|
||||
{valid ? (
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
<Translated i18nKey="verified" namespace="accounts" />{" "}
|
||||
{verifiedAt && moment(timestampDate(verifiedAt)).fromNow()}
|
||||
</span>
|
||||
) : (
|
||||
verifiedAt && (
|
||||
<span className="text-ellipsis text-xs opacity-80">
|
||||
<Translated i18nKey="expired" namespace="accounts" />{" "}
|
||||
{session.expirationDate &&
|
||||
moment(timestampDate(session.expirationDate)).fromNow()}
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
|
||||
<span className="flex-grow"></span>
|
||||
<div className="relative flex flex-row items-center">
|
||||
{valid ? (
|
||||
<div className="absolute right-6 mx-2 h-2 w-2 transform rounded-full bg-green-500 transition-all group-hover:right-6 sm:right-0"></div>
|
||||
) : (
|
||||
<div className="absolute right-6 mx-2 h-2 w-2 transform rounded-full bg-red-500 transition-all group-hover:right-6 sm:right-0"></div>
|
||||
)}
|
||||
|
||||
<XCircleIcon
|
||||
className="h-5 w-5 opacity-50 transition-all hover:opacity-100 group-hover:block sm:hidden"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
clearSessionId(session.id).then(() => {
|
||||
reload();
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</Tooltip.Trigger>
|
||||
{valid && session.expirationDate && (
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content
|
||||
className="z-50 select-none rounded-md border bg-background-light-500 px-3 py-2 text-xs text-black shadow-xl dark:border-white/20 dark:bg-background-dark-500 dark:text-white"
|
||||
sideOffset={5}
|
||||
>
|
||||
Expires {moment(timestampDate(session.expirationDate)).fromNow()}
|
||||
<Tooltip.Arrow className="fill-white dark:fill-white/20" />
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
)}
|
||||
</Tooltip.Root>
|
||||
);
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_
|
||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { FieldValues, useForm } from "react-hook-form";
|
||||
import { Alert, AlertType } from "./alert";
|
||||
import { BackButton } from "./back-button";
|
||||
@@ -59,6 +60,8 @@ export function SetPasswordForm({
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("password");
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
@@ -216,7 +219,7 @@ export function SetPasswordForm({
|
||||
type="text"
|
||||
required
|
||||
{...register("code", {
|
||||
required: "This field is required",
|
||||
required: t("set.required.code"),
|
||||
})}
|
||||
label="Code"
|
||||
autoComplete="one-time-code"
|
||||
@@ -231,7 +234,7 @@ export function SetPasswordForm({
|
||||
autoComplete="new-password"
|
||||
required
|
||||
{...register("password", {
|
||||
required: "You have to provide a password!",
|
||||
required: t("set.required.newPassword"),
|
||||
})}
|
||||
label="New Password"
|
||||
error={errors.password?.message as string}
|
||||
@@ -244,7 +247,7 @@ export function SetPasswordForm({
|
||||
required
|
||||
autoComplete="new-password"
|
||||
{...register("confirmPassword", {
|
||||
required: "This field is required",
|
||||
required: t("set.required.confirmPassword"),
|
||||
})}
|
||||
label="Confirm Password"
|
||||
error={errors.confirmPassword?.message as string}
|
||||
|
@@ -10,6 +10,7 @@ import { registerUser } from "@/lib/server/register";
|
||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { FieldValues, useForm } from "react-hook-form";
|
||||
import { Alert } from "./alert";
|
||||
import { BackButton } from "./back-button";
|
||||
@@ -52,6 +53,8 @@ export function SetRegisterPasswordForm({
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("register");
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
@@ -115,7 +118,7 @@ export function SetRegisterPasswordForm({
|
||||
autoComplete="new-password"
|
||||
required
|
||||
{...register("password", {
|
||||
required: "You have to provide a password!",
|
||||
required: t("password.required.password"),
|
||||
})}
|
||||
label="Password"
|
||||
error={errors.password?.message as string}
|
||||
@@ -128,7 +131,7 @@ export function SetRegisterPasswordForm({
|
||||
required
|
||||
autoComplete="new-password"
|
||||
{...register("confirmPassword", {
|
||||
required: "This field is required",
|
||||
required: t("password.required.confirmPassword"),
|
||||
})}
|
||||
label="Confirm Password"
|
||||
error={errors.confirmPassword?.message as string}
|
||||
|
@@ -7,6 +7,7 @@ import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { QRCodeSVG } from "qrcode.react";
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { Alert } from "./alert";
|
||||
import { Button, ButtonVariants } from "./button";
|
||||
@@ -49,6 +50,8 @@ export function TotpRegister({
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("otp");
|
||||
|
||||
async function continueWithCode(values: Inputs) {
|
||||
setLoading(true);
|
||||
return verifyTOTP(values.code, loginName, organization)
|
||||
@@ -122,7 +125,7 @@ export function TotpRegister({
|
||||
<div className="">
|
||||
<TextInput
|
||||
type="text"
|
||||
{...register("code", { required: "This field is required" })}
|
||||
{...register("code", { required: t("set.required.code") })}
|
||||
label="Code"
|
||||
data-testid="code-text-input"
|
||||
/>
|
||||
|
@@ -11,6 +11,7 @@ import { Button, ButtonVariants } from "./button";
|
||||
import { TextInput } from "./input";
|
||||
import { Spinner } from "./spinner";
|
||||
import { Translated } from "./translated";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type Inputs = {
|
||||
loginName: string;
|
||||
@@ -42,6 +43,8 @@ export function UsernameForm({
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("loginname");
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
@@ -101,7 +104,7 @@ export function UsernameForm({
|
||||
<TextInput
|
||||
type="text"
|
||||
autoComplete="username"
|
||||
{...register("loginName", { required: "This field is required" })}
|
||||
{...register("loginName", { required: t("required.loginName") })}
|
||||
label={inputLabel}
|
||||
data-testid="username-text-input"
|
||||
suffix={suffix}
|
||||
|
@@ -4,6 +4,7 @@ import { Alert, AlertType } from "@/components/alert";
|
||||
import { resendVerification, sendVerification } from "@/lib/server/verify";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { BackButton } from "./back-button";
|
||||
import { Button, ButtonVariants } from "./button";
|
||||
@@ -41,6 +42,8 @@ export function VerifyForm({
|
||||
},
|
||||
});
|
||||
|
||||
const t = useTranslations("verify");
|
||||
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
@@ -135,7 +138,7 @@ export function VerifyForm({
|
||||
<TextInput
|
||||
type="text"
|
||||
autoComplete="one-time-code"
|
||||
{...register("code", { required: "This field is required" })}
|
||||
{...register("code", { required: t("verify.required.code") })}
|
||||
label="Code"
|
||||
data-testid="code-text-input"
|
||||
/>
|
||||
|
@@ -242,7 +242,7 @@ export async function getSessionCookieByLoginName<T>({
|
||||
*/
|
||||
export async function getAllSessionCookieIds<T>(
|
||||
cleanup: boolean = false,
|
||||
): Promise<any> {
|
||||
): Promise<string[]> {
|
||||
const cookiesList = await cookies();
|
||||
const stringifiedCookie = cookiesList.get("sessions");
|
||||
|
||||
|
@@ -31,6 +31,10 @@ export const LANGS: Lang[] = [
|
||||
{
|
||||
name: "Русский",
|
||||
code: "ru",
|
||||
},
|
||||
{
|
||||
name: "Türkçe",
|
||||
code: "tr",
|
||||
},
|
||||
];
|
||||
|
||||
|
@@ -44,6 +44,8 @@ export async function setSAMLFormCookie(value: string): Promise<string> {
|
||||
name: uid,
|
||||
value: value,
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production", // Required for HTTPS in production
|
||||
sameSite: "lax", // Allows cookies with top-level navigation (needed for SAML redirects)
|
||||
path: "/",
|
||||
maxAge: 5 * 60, // 5 minutes
|
||||
});
|
||||
|
@@ -55,10 +55,21 @@ export async function createSessionAndUpdateCookie(command: {
|
||||
const _headers = await headers();
|
||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||
|
||||
let sessionLifetime = command.lifetime;
|
||||
|
||||
if (!sessionLifetime) {
|
||||
console.warn("No session lifetime provided, using default of 24 hours.");
|
||||
|
||||
sessionLifetime = {
|
||||
seconds: BigInt(24 * 60 * 60), // 24 hours
|
||||
nanos: 0,
|
||||
} as Duration; // for usecases where the lifetime is not specified (user discovery)
|
||||
}
|
||||
|
||||
const createdSession = await createSessionFromChecks({
|
||||
serviceUrl,
|
||||
checks: command.checks,
|
||||
lifetime: command.lifetime,
|
||||
lifetime: sessionLifetime,
|
||||
});
|
||||
|
||||
if (createdSession) {
|
||||
@@ -126,11 +137,24 @@ export async function createSessionForIdpAndUpdateCookie({
|
||||
const _headers = await headers();
|
||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||
|
||||
let sessionLifetime = lifetime;
|
||||
|
||||
if (!sessionLifetime) {
|
||||
console.warn(
|
||||
"No IDP session lifetime provided, using default of 24 hours.",
|
||||
);
|
||||
|
||||
sessionLifetime = {
|
||||
seconds: BigInt(24 * 60 * 60), // 24 hours
|
||||
nanos: 0,
|
||||
} as Duration;
|
||||
}
|
||||
|
||||
const createdSession = await createSessionForUserIdAndIdpIntent({
|
||||
serviceUrl,
|
||||
userId,
|
||||
idpIntent,
|
||||
lifetime,
|
||||
lifetime: sessionLifetime,
|
||||
}).catch((error: ErrorDetail | CredentialsCheckError) => {
|
||||
console.error("Could not set session", error);
|
||||
if ("failedAttempts" in error && error.failedAttempts) {
|
||||
@@ -190,41 +214,41 @@ export type SessionWithChallenges = Session & {
|
||||
challenges: Challenges | undefined;
|
||||
};
|
||||
|
||||
export async function setSessionAndUpdateCookie(
|
||||
recentCookie: CustomCookieData,
|
||||
checks?: Checks,
|
||||
challenges?: RequestChallenges,
|
||||
requestId?: string,
|
||||
lifetime?: Duration,
|
||||
) {
|
||||
export async function setSessionAndUpdateCookie(command: {
|
||||
recentCookie: CustomCookieData;
|
||||
checks?: Checks;
|
||||
challenges?: RequestChallenges;
|
||||
requestId?: string;
|
||||
lifetime: Duration;
|
||||
}) {
|
||||
const _headers = await headers();
|
||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||
|
||||
return setSession({
|
||||
serviceUrl,
|
||||
sessionId: recentCookie.id,
|
||||
sessionToken: recentCookie.token,
|
||||
challenges,
|
||||
checks,
|
||||
lifetime,
|
||||
sessionId: command.recentCookie.id,
|
||||
sessionToken: command.recentCookie.token,
|
||||
challenges: command.challenges,
|
||||
checks: command.checks,
|
||||
lifetime: command.lifetime,
|
||||
})
|
||||
.then((updatedSession) => {
|
||||
if (updatedSession) {
|
||||
const sessionCookie: CustomCookieData = {
|
||||
id: recentCookie.id,
|
||||
id: command.recentCookie.id,
|
||||
token: updatedSession.sessionToken,
|
||||
creationTs: recentCookie.creationTs,
|
||||
expirationTs: recentCookie.expirationTs,
|
||||
creationTs: command.recentCookie.creationTs,
|
||||
expirationTs: command.recentCookie.expirationTs,
|
||||
// just overwrite the changeDate with the new one
|
||||
changeTs: updatedSession.details?.changeDate
|
||||
? `${timestampMs(updatedSession.details.changeDate)}`
|
||||
: "",
|
||||
loginName: recentCookie.loginName,
|
||||
organization: recentCookie.organization,
|
||||
loginName: command.recentCookie.loginName,
|
||||
organization: command.recentCookie.organization,
|
||||
};
|
||||
|
||||
if (requestId) {
|
||||
sessionCookie.requestId = requestId;
|
||||
if (command.requestId) {
|
||||
sessionCookie.requestId = command.requestId;
|
||||
}
|
||||
|
||||
return getSession({
|
||||
|
@@ -1,83 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import { setSessionAndUpdateCookie } from "@/lib/server/cookie";
|
||||
import { create } from "@zitadel/client";
|
||||
import {
|
||||
CheckOTPSchema,
|
||||
ChecksSchema,
|
||||
CheckTOTPSchema,
|
||||
} from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { headers } from "next/headers";
|
||||
import {
|
||||
getMostRecentSessionCookie,
|
||||
getSessionCookieById,
|
||||
getSessionCookieByLoginName,
|
||||
} from "../cookies";
|
||||
import { getServiceUrlFromHeaders } from "../service-url";
|
||||
import { getLoginSettings } from "../zitadel";
|
||||
|
||||
export type SetOTPCommand = {
|
||||
loginName?: string;
|
||||
sessionId?: string;
|
||||
organization?: string;
|
||||
requestId?: string;
|
||||
code: string;
|
||||
method: string;
|
||||
};
|
||||
|
||||
export async function setOTP(command: SetOTPCommand) {
|
||||
const _headers = await headers();
|
||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||
|
||||
const recentSession = command.sessionId
|
||||
? await getSessionCookieById({ sessionId: command.sessionId }).catch(
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
},
|
||||
)
|
||||
: command.loginName
|
||||
? await getSessionCookieByLoginName({
|
||||
loginName: command.loginName,
|
||||
organization: command.organization,
|
||||
}).catch((error) => {
|
||||
return Promise.reject(error);
|
||||
})
|
||||
: await getMostRecentSessionCookie().catch((error) => {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
const checks = create(ChecksSchema, {});
|
||||
|
||||
if (command.method === "time-based") {
|
||||
checks.totp = create(CheckTOTPSchema, {
|
||||
code: command.code,
|
||||
});
|
||||
} else if (command.method === "sms") {
|
||||
checks.otpSms = create(CheckOTPSchema, {
|
||||
code: command.code,
|
||||
});
|
||||
} else if (command.method === "email") {
|
||||
checks.otpEmail = create(CheckOTPSchema, {
|
||||
code: command.code,
|
||||
});
|
||||
}
|
||||
|
||||
const loginSettings = await getLoginSettings({
|
||||
serviceUrl,
|
||||
organization: command.organization,
|
||||
});
|
||||
|
||||
return setSessionAndUpdateCookie(
|
||||
recentSession,
|
||||
checks,
|
||||
undefined,
|
||||
command.requestId,
|
||||
loginSettings?.secondFactorCheckLifetime,
|
||||
).then((session) => {
|
||||
return {
|
||||
sessionId: session.id,
|
||||
factors: session.factors,
|
||||
challenges: session.challenges,
|
||||
};
|
||||
});
|
||||
}
|
@@ -211,19 +211,27 @@ export async function sendPasskey(command: SendPasskeyCommand) {
|
||||
organization,
|
||||
});
|
||||
|
||||
const lifetime = checks?.webAuthN
|
||||
let lifetime = checks?.webAuthN
|
||||
? loginSettings?.multiFactorCheckLifetime // TODO different lifetime for webauthn u2f/passkey
|
||||
: checks?.otpEmail || checks?.otpSms
|
||||
? loginSettings?.secondFactorCheckLifetime
|
||||
: undefined;
|
||||
|
||||
const session = await setSessionAndUpdateCookie(
|
||||
recentSession,
|
||||
if (!lifetime) {
|
||||
console.warn("No passkey lifetime provided, defaulting to 24 hours");
|
||||
|
||||
lifetime = {
|
||||
seconds: BigInt(60 * 60 * 24), // default to 24 hours
|
||||
nanos: 0,
|
||||
} as Duration;
|
||||
}
|
||||
|
||||
const session = await setSessionAndUpdateCookie({
|
||||
recentCookie: recentSession,
|
||||
checks,
|
||||
undefined,
|
||||
requestId,
|
||||
lifetime,
|
||||
);
|
||||
});
|
||||
|
||||
if (!session || !session?.factors?.user?.id) {
|
||||
return { error: "Could not update session" };
|
||||
|
@@ -16,7 +16,7 @@ import {
|
||||
setPassword,
|
||||
setUserPassword,
|
||||
} from "@/lib/zitadel";
|
||||
import { ConnectError, create } from "@zitadel/client";
|
||||
import { ConnectError, create, Duration } from "@zitadel/client";
|
||||
import { createUserServiceClient } from "@zitadel/client/v2";
|
||||
import {
|
||||
Checks,
|
||||
@@ -152,14 +152,32 @@ export async function sendPassword(command: UpdateSessionCommand) {
|
||||
// this is a fake error message to hide that the user does not even exist
|
||||
return { error: "Could not verify password" };
|
||||
} else {
|
||||
loginSettings = await getLoginSettings({
|
||||
serviceUrl,
|
||||
organization: sessionCookie.organization,
|
||||
});
|
||||
|
||||
if (!loginSettings) {
|
||||
return { error: "Could not load login settings" };
|
||||
}
|
||||
|
||||
let lifetime = loginSettings.passwordCheckLifetime;
|
||||
|
||||
if (!lifetime) {
|
||||
console.warn("No password lifetime provided, defaulting to 24 hours");
|
||||
lifetime = {
|
||||
seconds: BigInt(60 * 60 * 24), // default to 24 hours
|
||||
nanos: 0,
|
||||
} as Duration;
|
||||
}
|
||||
|
||||
try {
|
||||
session = await setSessionAndUpdateCookie(
|
||||
sessionCookie,
|
||||
command.checks,
|
||||
undefined,
|
||||
command.requestId,
|
||||
loginSettings?.passwordCheckLifetime,
|
||||
);
|
||||
session = await setSessionAndUpdateCookie({
|
||||
recentCookie: sessionCookie,
|
||||
checks: command.checks,
|
||||
requestId: command.requestId,
|
||||
lifetime,
|
||||
});
|
||||
} catch (error: any) {
|
||||
if ("failedAttempts" in error && error.failedAttempts) {
|
||||
const lockoutSettings = await getLockoutSettings({
|
||||
|
@@ -154,19 +154,27 @@ export async function updateSession(options: UpdateSessionCommand) {
|
||||
organization,
|
||||
});
|
||||
|
||||
const lifetime = checks?.webAuthN
|
||||
let lifetime = checks?.webAuthN
|
||||
? loginSettings?.multiFactorCheckLifetime // TODO different lifetime for webauthn u2f/passkey
|
||||
: checks?.otpEmail || checks?.otpSms
|
||||
? loginSettings?.secondFactorCheckLifetime
|
||||
: undefined;
|
||||
|
||||
const session = await setSessionAndUpdateCookie(
|
||||
recentSession,
|
||||
if (!lifetime) {
|
||||
console.warn("No lifetime provided for session, defaulting to 24 hours");
|
||||
lifetime = {
|
||||
seconds: BigInt(60 * 60 * 24), // default to 24 hours
|
||||
nanos: 0,
|
||||
} as Duration;
|
||||
}
|
||||
|
||||
const session = await setSessionAndUpdateCookie({
|
||||
recentCookie: recentSession,
|
||||
checks,
|
||||
challenges,
|
||||
requestId,
|
||||
lifetime,
|
||||
);
|
||||
});
|
||||
|
||||
if (!session) {
|
||||
return { error: "Could not update session" };
|
||||
|
@@ -298,7 +298,7 @@ export async function createSessionFromChecks({
|
||||
}: {
|
||||
serviceUrl: string;
|
||||
checks: Checks;
|
||||
lifetime?: Duration;
|
||||
lifetime: Duration;
|
||||
}) {
|
||||
const sessionService: Client<typeof SessionService> =
|
||||
await createServiceForHost(SessionService, serviceUrl);
|
||||
@@ -320,7 +320,7 @@ export async function createSessionForUserIdAndIdpIntent({
|
||||
idpIntentId?: string | undefined;
|
||||
idpIntentToken?: string | undefined;
|
||||
};
|
||||
lifetime?: Duration;
|
||||
lifetime: Duration;
|
||||
}) {
|
||||
const sessionService: Client<typeof SessionService> =
|
||||
await createServiceForHost(SessionService, serviceUrl);
|
||||
@@ -355,7 +355,7 @@ export async function setSession({
|
||||
sessionToken: string;
|
||||
challenges: RequestChallenges | undefined;
|
||||
checks?: Checks;
|
||||
lifetime?: Duration;
|
||||
lifetime: Duration;
|
||||
}) {
|
||||
const sessionService: Client<typeof SessionService> =
|
||||
await createServiceForHost(SessionService, serviceUrl);
|
||||
@@ -1016,44 +1016,10 @@ export async function startIdentityProviderFlow({
|
||||
|
||||
return `${redirectUrl}?${params.toString()}`;
|
||||
} catch (stringifyError) {
|
||||
console.error("Failed to stringify formData.fields:", {
|
||||
error: stringifyError,
|
||||
formDataFields: formData.fields,
|
||||
formDataUrl: formData.url,
|
||||
fieldsType: typeof formData.fields,
|
||||
fieldsConstructor: formData.fields?.constructor?.name,
|
||||
});
|
||||
|
||||
// Try to create a safe serialization by converting to plain object
|
||||
try {
|
||||
const safeFields: Record<string, string> = {};
|
||||
const fieldsObj = formData.fields || {};
|
||||
|
||||
// Convert each field to a string if it's not already
|
||||
for (const [key, value] of Object.entries(fieldsObj)) {
|
||||
safeFields[key] =
|
||||
typeof value === "string" ? value : String(value);
|
||||
}
|
||||
|
||||
console.log(
|
||||
"Using safe serialization for formData.fields:",
|
||||
safeFields,
|
||||
);
|
||||
|
||||
const safeStringified = JSON.stringify(safeFields);
|
||||
const dataId = await setSAMLFormCookie(safeStringified);
|
||||
const params = new URLSearchParams({
|
||||
url: formData.url,
|
||||
id: dataId,
|
||||
});
|
||||
|
||||
return `${redirectUrl}?${params.toString()}`;
|
||||
} catch (fallbackError) {
|
||||
console.error("Safe serialization also failed:", fallbackError);
|
||||
throw new Error(
|
||||
`Failed to serialize SAML form data: ${stringifyError instanceof Error ? stringifyError.message : String(stringifyError)}`,
|
||||
);
|
||||
}
|
||||
console.error("JSON serialization failed:", stringifyError);
|
||||
throw new Error(
|
||||
`Failed to serialize SAML form data: ${stringifyError instanceof Error ? stringifyError.message : String(stringifyError)}`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
|
@@ -19,6 +19,7 @@ import localeSv from '@angular/common/locales/sv';
|
||||
import localeHu from '@angular/common/locales/hu';
|
||||
import localeKo from '@angular/common/locales/ko';
|
||||
import localeRo from '@angular/common/locales/ro';
|
||||
import localeTr from '@angular/common/locales/tr';
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
@@ -112,6 +113,8 @@ registerLocaleData(localeKo);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/ko.json'));
|
||||
registerLocaleData(localeRo);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/ro.json'));
|
||||
registerLocaleData(localeTr);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/tr.json'));
|
||||
|
||||
export class WebpackTranslateLoader implements TranslateLoader {
|
||||
getTranslation(lang: string): Observable<any> {
|
||||
|
@@ -18,6 +18,7 @@ export const supportedLanguages = [
|
||||
'hu',
|
||||
'ko',
|
||||
'ro',
|
||||
'tr',
|
||||
];
|
||||
export const supportedLanguagesRegexp: RegExp = /de|en|es|fr|id|it|ja|pl|zh|bg|pt|mk|cs|ru|nl|sv|hu|ko|ro/;
|
||||
export const supportedLanguagesRegexp: RegExp = /de|en|es|fr|id|it|ja|pl|zh|bg|pt|mk|cs|ru|nl|sv|hu|ko|ro|tr/;
|
||||
export const fallbackLanguage: string = 'en';
|
||||
|
@@ -1544,7 +1544,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1793,7 +1794,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Проверката на имейл е извършена",
|
||||
@@ -2743,7 +2745,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Добавяне на мениджър",
|
||||
|
@@ -1545,7 +1545,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1794,7 +1795,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Ověření e-mailu dokončeno",
|
||||
@@ -2757,7 +2759,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Přidat manažera",
|
||||
|
@@ -1545,7 +1545,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1794,7 +1795,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Email Verification erfolgreich",
|
||||
@@ -2748,7 +2750,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Manager hinzufügen",
|
||||
|
@@ -1548,7 +1548,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1797,7 +1798,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Email verification done",
|
||||
@@ -2776,7 +2778,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Add a Manager",
|
||||
|
@@ -1546,7 +1546,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1795,7 +1796,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verificación de email realizada",
|
||||
@@ -2745,7 +2747,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Añadir un Mánager",
|
||||
|
@@ -1545,7 +1545,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1794,7 +1795,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Vérification de l'e-mail effectuée",
|
||||
@@ -2749,7 +2751,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Ajouter un responsable",
|
||||
|
@@ -1545,7 +1545,8 @@
|
||||
"id": "Indonéz",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1792,7 +1793,8 @@
|
||||
"id": "Indonéz",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "E-mail ellenőrzés kész",
|
||||
@@ -2771,7 +2773,8 @@
|
||||
"id": "Indonéz",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Hozzáadás egy menedzsert",
|
||||
|
@@ -1423,7 +1423,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1658,7 +1659,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verifikasi email selesai",
|
||||
@@ -2456,7 +2458,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Tambahkan Manajer",
|
||||
|
@@ -1545,7 +1545,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1794,7 +1795,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verifica dell'e-mail terminata con successo.",
|
||||
@@ -2749,7 +2751,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Aggiungi un manager",
|
||||
|
@@ -1545,7 +1545,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1794,7 +1795,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "メール認証が完了しました",
|
||||
@@ -2773,7 +2775,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "マネージャーを追加する",
|
||||
|
@@ -1545,7 +1545,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1794,7 +1795,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "이메일 인증 완료",
|
||||
@@ -2769,7 +2771,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "매니저 추가",
|
||||
|
@@ -1546,7 +1546,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1795,7 +1796,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Е-поштата е верифицирана",
|
||||
@@ -2745,7 +2747,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Додај Менаџер",
|
||||
|
@@ -1545,7 +1545,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1794,7 +1795,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "E-mail verificatie voltooid",
|
||||
@@ -2766,7 +2768,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Voeg een Manager toe",
|
||||
|
@@ -1544,7 +1544,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1793,7 +1794,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Weryfikacja adresu e-mail zakończona",
|
||||
@@ -2748,7 +2750,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Dodaj managera",
|
||||
|
@@ -1546,7 +1546,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1795,7 +1796,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verificação de email concluída",
|
||||
@@ -2744,7 +2746,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Adicionar um Gerente",
|
||||
|
@@ -1543,7 +1543,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1792,7 +1793,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verificarea e-mailului efectuată",
|
||||
@@ -2769,7 +2771,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Adăugați un manager",
|
||||
|
@@ -1590,7 +1590,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1851,7 +1852,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"LOCALE": "Код языка",
|
||||
"LOCALES": {
|
||||
@@ -2857,7 +2859,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Добавить менеджера",
|
||||
|
@@ -1549,7 +1549,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1798,7 +1799,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "E-postverifiering klar",
|
||||
@@ -2777,7 +2779,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Lägg till en administratör",
|
||||
|
2859
console/src/assets/i18n/tr.json
Normal file
@@ -1545,7 +1545,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@@ -1793,7 +1794,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "电子邮件验证完成",
|
||||
@@ -2748,7 +2750,8 @@
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어",
|
||||
"ro": "Română"
|
||||
"ro": "Română",
|
||||
"tr": "Türkçe"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "添加管理者",
|
||||
|
@@ -3,12 +3,16 @@ title: ZITADEL with Go
|
||||
sidebar_label: Go
|
||||
---
|
||||
|
||||
This integration guide demonstrates the recommended way to incorporate ZITADEL into your Go web application.
|
||||
This integration guide demonstrates the recommended way to incorporate ZITADEL into your Go web application.
|
||||
It explains how to enable user login in your application and how to fetch data from the user info endpoint.
|
||||
|
||||
> ℹ️ These examples and guides are based on our official [Go SDK](https://github.com/zitadel/zitadel-go).
|
||||
>
|
||||
> The SDK is a convenient wrapper around our low-level [OIDC library](https://github.com/zitadel/oidc). For most use cases, using the helpers provided in our [Go SDK](https://github.com/zitadel/zitadel-go) is the recommended approach for implementing authentication.
|
||||
|
||||
By the end of this guide, your application will have login functionality and will be able to access the current user's profile.
|
||||
|
||||
> This documentation references our [example](https://github.com/zitadel/zitadel-go) on GitHub.
|
||||
> This documentation references our [example](https://github.com/zitadel/zitadel-go) on GitHub.
|
||||
> You can either create your own application or directly run the example by providing the necessary arguments.
|
||||
|
||||
## Set up application
|
||||
@@ -86,7 +90,7 @@ To ensure the user is authenticated before they are able to use your application
|
||||
```go
|
||||
mw.CheckAuthentication()(handler)
|
||||
```
|
||||
|
||||
|
||||
***Authentication context***
|
||||
|
||||
If you used either of the authentication checks above, you can then access context information in your handler:
|
||||
@@ -119,7 +123,7 @@ https://github.com/zitadel/zitadel-go/blob/next/example/app/templates/profile.ht
|
||||
|
||||
You will need to provide some values for the program to run:
|
||||
- `domain`: Your ZITADEL instance domain, e.g. my-domain.zitadel.cloud
|
||||
- `key`: Random secret string. Used for symmetric encryption of state parameters, cookies and PCKE.
|
||||
- `key`: Random secret string. Used for symmetric encryption of state parameters, cookies and PCKE.
|
||||
- `clientID`: The clientID provided by ZITADEL
|
||||
- `redirectURI`: The redirectURI registered at ZITADEL
|
||||
- `port`: The port on which the API will be accessible, default it 8089
|
||||
@@ -146,7 +150,7 @@ By clicking on `Login` you will be redirected to your ZITADEL instance. After lo
|
||||
|
||||
Congratulations! You have successfully integrated your Go application with ZITADEL!
|
||||
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/zitadel-go) application.
|
||||
This application includes all the functionalities mentioned in this quickstart.
|
||||
If you get stuck, consider checking out our [example](https://github.com/zitadel/zitadel-go) application.
|
||||
This application includes all the functionalities mentioned in this quickstart.
|
||||
You can directly start it with your own configuration. If you face issues, contact us or raise an issue on [GitHub](https://github.com/zitadel/zitadel-go/issues).
|
||||
|
||||
|
@@ -6,13 +6,17 @@ sidebar_label: Go
|
||||
This integration guide shows you how to integrate **ZITADEL** into your Go API. It demonstrates how to secure your API using
|
||||
OAuth 2 Token Introspection.
|
||||
|
||||
> ℹ️ These examples and guides are based on our official [Go SDK](https://github.com/zitadel/zitadel-go).
|
||||
>
|
||||
> The SDK is a convenient wrapper around our low-level [OIDC library](https://github.com/zitadel/oidc). For most use cases, using the helpers provided in our [Go SDK](https://github.com/zitadel/zitadel-go) is the recommended approach for implementing authentication.
|
||||
|
||||
At the end of the guide you should have an API with a protected endpoint.
|
||||
|
||||
> This documentation references our HTTP example. There's also one for GRPC. Check them out on [GitHub](https://github.com/zitadel/zitadel-go/blob/next/example/api/http/main.go).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This will handle the OAuth 2.0 introspection request including authentication using JWT with Private Key using our [OIDC client library](https://github.com/zitadel/oidc).
|
||||
This will handle the OAuth 2.0 introspection request including authentication using JWT with Private Key using our [Go SDK](https://github.com/zitadel/zitadel-go).
|
||||
All that is required, is to create your API, create a private key and a personal access token for a service user.
|
||||
|
||||
### Set up application and obtain keys
|
||||
@@ -125,7 +129,7 @@ Now you can call the API by browser or curl. Try the healthz endpoint first:
|
||||
curl -i http://localhost:8089/api/healthz
|
||||
```
|
||||
|
||||
it should return something like:
|
||||
it should return something like:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
|
@@ -6,13 +6,17 @@ sidebar_label: Example Go
|
||||
This integration guide shows you how to integrate **ZITADEL** into your Go application.
|
||||
It demonstrates how to fetch some data from the ZITADEL management API.
|
||||
|
||||
> ℹ️ These examples and guides are based on our official [Go SDK](https://github.com/zitadel/zitadel-go).
|
||||
>
|
||||
> The SDK is a convenient wrapper around our low-level [OIDC library](https://github.com/zitadel/oidc). For most use cases, using the helpers provided in our [Go SDK](https://github.com/zitadel/zitadel-go) is the recommended approach for implementing authentication.
|
||||
|
||||
At the end of the guide you should have an application able to read the details of your organization.
|
||||
|
||||
> This documentation references our [CLI example](https://github.com/zitadel/zitadel-go/blob/next/example/client/cli/cli.go).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The client [SDK](https://github.com/zitadel/zitadel-go) will handle all necessary OAuth 2.0 requests and send the required headers to the ZITADEL API using our [OIDC client library](https://github.com/zitadel/oidc).
|
||||
The client [SDK](https://github.com/zitadel/zitadel-go) will handle all necessary OAuth 2.0 requests and send the required headers to the ZITADEL API using our [Go SDK](https://github.com/zitadel/zitadel-go).
|
||||
All that is required, is a service account with an Org Owner (or another role, depending on the needed api requests) role assigned and its key JSON.
|
||||
|
||||
However, we recommend you read the guide on [how to access ZITADEL API](/docs/guides/integrate/zitadel-apis/access-zitadel-apis)) and the associated guides for a basic knowledge of :
|
||||
@@ -64,7 +68,7 @@ This will output something similar to:
|
||||
|
||||
You have successfully used the ZITADEL Go SDK to call the management API!
|
||||
|
||||
If you encountered an error (e.g. `code = PermissionDenied desc = No matching permissions found`),
|
||||
If you encountered an error (e.g. `code = PermissionDenied desc = No matching permissions found`),
|
||||
ensure your service user has the required permissions by assigning the `ORG_OWNER` or `ORG_OWNER_VIEWER` role
|
||||
and check the mentioned [guides](#prerequisites) at the beginning.
|
||||
|
||||
|
@@ -53,6 +53,7 @@ ZITADEL is available in the following languages
|
||||
- Hungarian (hu)
|
||||
- 한국어 (ko)
|
||||
- Romanian (ro)
|
||||
- Turkish (tr)
|
||||
|
||||
A language is displayed based on your agent's language header.
|
||||
If a users language header doesn't match any of the supported or [restricted](#restrict-languages) languages, the instances default language will be used.
|
||||
|
4
docs/docs/sdk-examples/client-libraries/_category_.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Client Libraries",
|
||||
"position": 2
|
||||
}
|
194
docs/docs/sdk-examples/client-libraries/java.mdx
Normal file
@@ -0,0 +1,194 @@
|
||||
---
|
||||
title: Java Client
|
||||
sidebar_label: 'Java Client'
|
||||
---
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px">
|
||||
<img width="100px" src="/docs/img/tech/java.svg" alt="java logo"/>
|
||||
</td>
|
||||
<td>
|
||||
This guide covers the official Zitadel Management API Client for the JVM (Java 11+), which allows you to programmatically manage resources in your Zitadel instance.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
:::info
|
||||
**This is a Management API Client, not an Authentication SDK.**
|
||||
|
||||
This library is designed for server-to-server communication to manage your Zitadel instance (e.g., creating users, managing projects, and updating settings). It is **not** intended for handling end-user login flows in your web application. For user authentication, you should use a standard OIDC library like Spring Security.
|
||||
:::
|
||||
|
||||
The Zitadel Java Client provides an idiomatic way to access the full gamut of Zitadel's v2 Management APIs from your JVM-based backend applications.
|
||||
|
||||
> Please be aware that this client library is currently in an **incubating stage**.
|
||||
While it is available for use, the API and its functionality may evolve, potentially introducing
|
||||
breaking changes in future updates. We advise caution when considering it for production environments.
|
||||
|
||||
### Installation
|
||||
|
||||
You can add the client library to your project using Maven by adding the following dependency to your `pom.xml` :
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.zitadel</groupId>
|
||||
<artifactId>client</artifactId>
|
||||
<version>4.0.0-beta-1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### Using the SDK
|
||||
|
||||
Your SDK offers three ways to authenticate with Zitadel. Each method has its
|
||||
own benefits—choose the one that fits your situation best.
|
||||
|
||||
#### 1. Private Key JWT Authentication
|
||||
|
||||
**What is it?**
|
||||
You use a JSON Web Token (JWT) that you sign with a private key stored in a
|
||||
JSON file. This process creates a secure token.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Best for production:** It offers strong security.
|
||||
- **Advanced control:** You can adjust token settings like expiration.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Save your private key in a JSON file.
|
||||
2. Build the authenticator using the helper method.
|
||||
|
||||
**Example:**
|
||||
|
||||
```java
|
||||
import com.zitadel.ApiException;
|
||||
import com.zitadel.Zitadel;
|
||||
import com.zitadel.model.UserServiceAddHumanUserRequest;
|
||||
import com.zitadel.model.UserServiceAddHumanUserResponse;
|
||||
import com.zitadel.model.UserServiceSetHumanEmail;
|
||||
import com.zitadel.model.UserServiceSetHumanProfile;
|
||||
|
||||
class Demo {
|
||||
public static void main(String[] args) throws ApiException {
|
||||
Zitadel zitadel = Zitadel.withPrivateKey("https://example.us1.zitadel.cloud", "path/to/jwt-key.json");
|
||||
|
||||
UserServiceAddHumanUserResponse response = zitadel.users.userServiceAddHumanUser(
|
||||
new UserServiceAddHumanUserRequest()
|
||||
.username("john.doe")
|
||||
.profile(new UserServiceSetHumanProfile()
|
||||
.givenName("John")
|
||||
.familyName("Doe"))
|
||||
.email(new UserServiceSetHumanEmail()
|
||||
.email("john@doe.com"))
|
||||
);
|
||||
System.out.println("User created: " + response);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Client Credentials Grant
|
||||
|
||||
**What is it?**
|
||||
This method uses a client ID and client secret to get a secure access token,
|
||||
which is then used to authenticate.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Simple and straightforward:** Good for server-to-server communication.
|
||||
- **Trusted environments:** Use it when both servers are owned or trusted.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Provide your client ID and client secret.
|
||||
2. Build the authenticator using the helper method.
|
||||
|
||||
**Example:**
|
||||
|
||||
```java
|
||||
import com.zitadel.ApiException;
|
||||
import com.zitadel.Zitadel;
|
||||
import com.zitadel.model.UserServiceAddHumanUserRequest;
|
||||
import com.zitadel.model.UserServiceAddHumanUserResponse;
|
||||
import com.zitadel.model.UserServiceSetHumanEmail;
|
||||
import com.zitadel.model.UserServiceSetHumanProfile;
|
||||
|
||||
class Demo {
|
||||
public static void main(String[] args) throws ApiException {
|
||||
Zitadel zitadel = Zitadel.withClientCredentials("https://example.us1.zitadel.cloud", "id", "secret");
|
||||
|
||||
UserServiceAddHumanUserResponse response = zitadel.users.addHumanUser(
|
||||
new UserServiceAddHumanUserRequest()
|
||||
.username("john.doe")
|
||||
.profile(new UserServiceSetHumanProfile()
|
||||
.givenName("John")
|
||||
.familyName("Doe"))
|
||||
.email(new UserServiceSetHumanEmail()
|
||||
.email("john@doe.com"))
|
||||
);
|
||||
System.out.println("User created: " + response);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Personal Access Tokens (PATs)
|
||||
|
||||
**What is it?**
|
||||
A Personal Access Token (PAT) is a pre-generated token that you can use to
|
||||
authenticate without exchanging credentials every time.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Easy to use:** Great for development or testing scenarios.
|
||||
- **Quick setup:** No need for dynamic token generation.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Obtain a valid personal access token from your account.
|
||||
2. Build the authenticator using the helper method.
|
||||
|
||||
**Example:**
|
||||
|
||||
```java
|
||||
import com.zitadel.ApiException;
|
||||
import com.zitadel.Zitadel;
|
||||
import com.zitadel.model.UserServiceAddHumanUserRequest;
|
||||
import com.zitadel.model.UserServiceAddHumanUserResponse;
|
||||
import com.zitadel.model.UserServiceSetHumanEmail;
|
||||
import com.zitadel.model.UserServiceSetHumanProfile;
|
||||
|
||||
class Demo {
|
||||
|
||||
public static void main(String[] args) throws ApiException {
|
||||
Zitadel zitadel = Zitadel.withAccessToken("https://example.us1.zitadel.cloud", "token");
|
||||
|
||||
UserServiceAddHumanUserResponse response = zitadel.users.addHumanUser(
|
||||
new UserServiceAddHumanUserRequest()
|
||||
.username("john.doe")
|
||||
.profile(new UserServiceSetHumanProfile()
|
||||
.givenName("John")
|
||||
.familyName("Doe"))
|
||||
.email(new UserServiceSetHumanEmail()
|
||||
.email("john@doe.com"))
|
||||
);
|
||||
System.out.println("User created: " + response);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Choose the authentication method that best suits your needs based on your
|
||||
environment and security requirements. For more details, please refer to the
|
||||
[Zitadel documentation on authenticating service users](https://zitadel.com/docs/guides/integrate/service-users/authenticate-service-users).
|
||||
|
||||
### Versioning
|
||||
|
||||
The client library's versioning is aligned with the Zitadel core project. The major version of the
|
||||
client corresponds to the major version of Zitadel it is designed to work with. For example,
|
||||
v2.x.x of the client is built for and tested against Zitadel v2, ensuring a predictable and stable integration.
|
||||
|
||||
### Resources
|
||||
|
||||
- [GitHub Repository](https://github.com/zitadel/client-java): For source code, examples, and to report issues.
|
||||
- [Maven Package](https://central.sonatype.com/artifact/io.github.zitadel/client): The official package artifact for Maven.
|
193
docs/docs/sdk-examples/client-libraries/php.mdx
Normal file
@@ -0,0 +1,193 @@
|
||||
---
|
||||
title: PHP Client
|
||||
sidebar_label: 'PHP Client'
|
||||
---
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px">
|
||||
<img width="100px" src="/docs/img/tech/php.svg" alt="php logo"/>
|
||||
</td>
|
||||
<td>
|
||||
This guide covers the official Zitadel Management API Client for PHP, which allows you to programmatically manage resources in your Zitadel instance.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
:::info
|
||||
**This is a Management API Client, not an Authentication SDK.**
|
||||
|
||||
This library is designed for server-to-server communication to manage your Zitadel instance (e.g., creating users, managing projects, and updating settings). It is **not** intended for handling end-user login flows in your web application. For user authentication, you should use a standard OIDC library with your PHP framework of choice.
|
||||
:::
|
||||
|
||||
The Zitadel PHP Client provides an idiomatic way to access the full gamut of
|
||||
Zitadel's v2 Management APIs from your PHP backend.
|
||||
|
||||
> Please be aware that this client library is currently in an **incubating stage**.
|
||||
While it is available for use, the API and its functionality may evolve, potentially introducing
|
||||
breaking changes in future updates. We advise caution when considering it for production environments.
|
||||
|
||||
### Installation
|
||||
|
||||
You can add the client library to your project using Composer:
|
||||
|
||||
```bash
|
||||
composer require zitadel/client:"^4.0.0-beta1"
|
||||
```
|
||||
|
||||
### Using the SDK
|
||||
|
||||
Your SDK offers three ways to authenticate with Zitadel. Each method has its
|
||||
own benefits—choose the one that fits your situation best.
|
||||
|
||||
#### 1. Private Key JWT Authentication
|
||||
|
||||
**What is it?**
|
||||
You use a JSON Web Token (JWT) that you sign with a private key stored in a
|
||||
JSON file. This process creates a secure token.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Best for production:** It offers strong security.
|
||||
- **Advanced control:** You can adjust token settings like expiration.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Save your private key in a JSON file.
|
||||
2. Use the provided method to load this key and create a JWT-based
|
||||
authenticator.
|
||||
|
||||
**Example:**
|
||||
|
||||
```php
|
||||
use \Zitadel\Client\Zitadel;
|
||||
|
||||
$zitadel = Zitadel::withPrivateKey("https://example.us1.zitadel.cloud", "path/to/jwt-key.json");
|
||||
|
||||
try {
|
||||
$response = $zitadel->users->userServiceAddHumanUser([
|
||||
'username' => 'john.doe',
|
||||
'profile' => [
|
||||
'givenName' => 'John',
|
||||
'familyName' => 'Doe'
|
||||
],
|
||||
'email' => [
|
||||
'email' => 'john@doe.com'
|
||||
]
|
||||
]);
|
||||
echo "User created: " . print_r($response, true);
|
||||
} catch (ApiException $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Client Credentials Grant
|
||||
|
||||
**What is it?**
|
||||
This method uses a client ID and client secret to get a secure access token,
|
||||
which is then used to authenticate.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Simple and straightforward:** Good for server-to-server communication.
|
||||
- **Trusted environments:** Use it when both servers are owned or trusted.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Provide your client ID and client secret.
|
||||
2. Build the authenticator
|
||||
|
||||
**Example:**
|
||||
|
||||
```php
|
||||
use Zitadel\Client\Zitadel;
|
||||
use Zitadel\Client\Model\UserServiceAddHumanUserRequest;
|
||||
use \Zitadel\Client\Model\UserServiceAddHumanUserRequest;
|
||||
use \Zitadel\Client\Model\UserServiceSetHumanProfile;
|
||||
use \Zitadel\Client\Model\UserServiceSetHumanEmail;
|
||||
|
||||
$zitadel = Zitadel::withClientCredentials("https://example.us1.zitadel.cloud", "id", "secret");
|
||||
|
||||
try {
|
||||
$response = $zitadel->users->addHumanUser((new UserServiceAddHumanUserRequest())
|
||||
->setUsername('john.doe')
|
||||
->setProfile(
|
||||
(new UserServiceSetHumanProfile())
|
||||
->setGivenName('John')
|
||||
->setFamilyName('Doe')
|
||||
)
|
||||
->setEmail(
|
||||
(new UserServiceSetHumanEmail())
|
||||
->setEmail('john@doe.com')
|
||||
));
|
||||
echo "User created: " . print_r($response, true);
|
||||
} catch (ApiException $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Personal Access Tokens (PATs)
|
||||
|
||||
**What is it?**
|
||||
A Personal Access Token (PAT) is a pre-generated token that you can use to
|
||||
authenticate without exchanging credentials every time.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Easy to use:** Great for development or testing scenarios.
|
||||
- **Quick setup:** No need for dynamic token generation.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Obtain a valid personal access token from your account.
|
||||
2. Create the authenticator with: `PersonalAccessTokenAuthenticator`
|
||||
|
||||
**Example:**
|
||||
|
||||
```php
|
||||
use \Zitadel\Client\Zitadel;
|
||||
use Zitadel\Client\Zitadel;
|
||||
use Zitadel\Client\Model\UserServiceAddHumanUserRequest;
|
||||
use \Zitadel\Client\Model\UserServiceAddHumanUserRequest;
|
||||
use \Zitadel\Client\Model\UserServiceSetHumanProfile;
|
||||
use \Zitadel\Client\Model\UserServiceSetHumanEmail;
|
||||
|
||||
$zitadel = Zitadel::withAccessToken("https://example.us1.zitadel.cloud", "token");
|
||||
|
||||
try {
|
||||
$response = $zitadel->users->addHumanUser(
|
||||
(new UserServiceAddHumanUserRequest())
|
||||
->setUsername('john.doe')
|
||||
->setProfile(
|
||||
(new UserServiceSetHumanProfile())
|
||||
->setGivenName('John')
|
||||
->setFamilyName('Doe')
|
||||
)
|
||||
->setEmail(
|
||||
(new UserServiceSetHumanEmail())
|
||||
->setEmail('john@doe.com')
|
||||
)
|
||||
);
|
||||
echo "User created: " . print_r($response, true);
|
||||
} catch (ApiException $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Choose the authentication method that best suits your needs based on your
|
||||
environment and security requirements. For more details, please refer to the
|
||||
[Zitadel documentation on authenticating service users](https://zitadel.com/docs/guides/integrate/service-users/authenticate-service-users).
|
||||
|
||||
### Versioning
|
||||
|
||||
The client library's versioning is aligned with the Zitadel core project. The major version of the
|
||||
client corresponds to the major version of Zitadel it is designed to work with. For example,
|
||||
v2.x.x of the client is built for and tested against Zitadel v2, ensuring a predictable and stable integration.
|
||||
|
||||
### Resources
|
||||
|
||||
- [GitHub Repository](https://github.com/zitadel/client-php): For source code, examples, and to report issues.
|
||||
- [Packagist Package](https://packagist.org/packages/zitadel/client): The official package artifact for Composer.
|
||||
|
197
docs/docs/sdk-examples/client-libraries/python.mdx
Normal file
@@ -0,0 +1,197 @@
|
||||
---
|
||||
title: Python Client
|
||||
sidebar_label: 'Python Client'
|
||||
---
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px">
|
||||
<img width="100px" src="/docs/img/tech/python.svg" alt="python logo"/>
|
||||
</td>
|
||||
<td>
|
||||
This guide covers the official Zitadel Management API Client for Python (3.9+), which allows you to programmatically manage resources in your Zitadel instance.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
:::info
|
||||
**This is a Management API Client, not an Authentication SDK.**
|
||||
|
||||
This library is designed for server-to-server communication to manage your Zitadel instance (e.g., creating users, managing projects, and updating settings). It is **not** intended for handling end-user login flows in your web application. For user authentication, you should use a standard OIDC library with your Python framework of choice, such as `mozilla-django-oidc` for Django or `Authlib` for Flask.
|
||||
:::
|
||||
|
||||
The Zitadel Python Client provides an idiomatic way to access the full gamut of Zitadel's v2 Management APIs from your Python backend.
|
||||
|
||||
> Please be aware that this client library is currently in an **incubating stage**.
|
||||
While it is available for use, the API and its functionality may evolve, potentially introducing
|
||||
breaking changes in future updates. We advise caution when considering it for production environments.
|
||||
|
||||
### Installation
|
||||
|
||||
You can add the client library to your project using pip:
|
||||
|
||||
```bash
|
||||
pip install --pre zitadel-client
|
||||
```
|
||||
|
||||
### Using the SDK
|
||||
|
||||
Your SDK offers three ways to authenticate with Zitadel. Each method has its
|
||||
own benefits—choose the one that fits your situation best.
|
||||
|
||||
#### 1. Private Key JWT Authentication
|
||||
|
||||
**What is it?**
|
||||
You use a JSON Web Token (JWT) that you sign with a private key stored in a
|
||||
JSON file. This process creates a secure token.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Best for production:** It offers strong security.
|
||||
- **Advanced control:** You can adjust token settings like expiration.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Save your private key in a JSON file.
|
||||
2. Use the provided method to load this key and create a JWT-based
|
||||
authenticator.
|
||||
|
||||
**Example:**
|
||||
|
||||
```python
|
||||
import zitadel_client as zitadel
|
||||
from zitadel_client.exceptions import ApiError
|
||||
from zitadel_client.models import (
|
||||
UserServiceAddHumanUserRequest,
|
||||
UserServiceSetHumanEmail,
|
||||
UserServiceSetHumanProfile,
|
||||
)
|
||||
|
||||
zitadel = zitadel.Zitadel.with_private_key("https://example.us1.zitadel.cloud", "path/to/jwt-key.json")
|
||||
|
||||
try:
|
||||
request = UserServiceAddHumanUserRequest(
|
||||
username="john.doe",
|
||||
profile=UserServiceSetHumanProfile(
|
||||
givenName="John",
|
||||
familyName="Doe"
|
||||
),
|
||||
email=UserServiceSetHumanEmail(
|
||||
email="john@doe.com"
|
||||
),
|
||||
)
|
||||
response = zitadel.users.add_human_user(request)
|
||||
print("User created:", response)
|
||||
except ApiError as e:
|
||||
print("Error:", e)
|
||||
```
|
||||
|
||||
#### 2. Client Credentials Grant
|
||||
|
||||
**What is it?**
|
||||
This method uses a client ID and client secret to get a secure access token,
|
||||
which is then used to authenticate.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Simple and straightforward:** Good for server-to-server communication.
|
||||
- **Trusted environments:** Use it when both servers are owned or trusted.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Provide your client ID and client secret.
|
||||
2. Build the authenticator
|
||||
|
||||
**Example:**
|
||||
|
||||
```python
|
||||
import zitadel_client as zitadel
|
||||
from zitadel_client.exceptions import ApiError
|
||||
from zitadel_client.models import (
|
||||
UserServiceAddHumanUserRequest,
|
||||
UserServiceSetHumanEmail,
|
||||
UserServiceSetHumanProfile,
|
||||
)
|
||||
|
||||
zitadel = zitadel.Zitadel.with_client_credentials("https://example.us1.zitadel.cloud", "id", "secret")
|
||||
|
||||
try:
|
||||
request = UserServiceAddHumanUserRequest(
|
||||
username="john.doe",
|
||||
profile=UserServiceSetHumanProfile(
|
||||
givenName="John",
|
||||
familyName="Doe"
|
||||
),
|
||||
email=UserServiceSetHumanEmail(
|
||||
email="john@doe.com"
|
||||
),
|
||||
)
|
||||
response = zitadel.users.add_human_user(request)
|
||||
print("User created:", response)
|
||||
except ApiError as e:
|
||||
print("Error:", e)
|
||||
```
|
||||
|
||||
#### 3. Personal Access Tokens (PATs)
|
||||
|
||||
**What is it?**
|
||||
A Personal Access Token (PAT) is a pre-generated token that you can use to
|
||||
authenticate without exchanging credentials every time.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Easy to use:** Great for development or testing scenarios.
|
||||
- **Quick setup:** No need for dynamic token generation.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Obtain a valid personal access token from your account.
|
||||
2. Create the authenticator with: `PersonalAccessTokenAuthenticator`
|
||||
|
||||
**Example:**
|
||||
|
||||
```python
|
||||
import zitadel_client as zitadel
|
||||
from zitadel_client.exceptions import ApiError
|
||||
from zitadel_client.models import (
|
||||
UserServiceAddHumanUserRequest,
|
||||
UserServiceSetHumanEmail,
|
||||
UserServiceSetHumanProfile,
|
||||
)
|
||||
|
||||
zitadel = zitadel.Zitadel.with_access_token("https://example.us1.zitadel.cloud", "token")
|
||||
|
||||
try:
|
||||
request = UserServiceAddHumanUserRequest(
|
||||
username="john.doe",
|
||||
profile=UserServiceSetHumanProfile(
|
||||
givenName="John",
|
||||
familyName="Doe"
|
||||
),
|
||||
email=UserServiceSetHumanEmail(
|
||||
email="john@doe.com"
|
||||
),
|
||||
)
|
||||
response = zitadel.users.add_human_user(request)
|
||||
print("User created:", response)
|
||||
except ApiError as e:
|
||||
print("Error:", e)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Choose the authentication method that best suits your needs based on your
|
||||
environment and security requirements. For more details, please refer to the
|
||||
[Zitadel documentation on authenticating service users](https://zitadel.com/docs/guides/integrate/service-users/authenticate-service-users).
|
||||
|
||||
### Versioning
|
||||
|
||||
The client library's versioning is aligned with the Zitadel core project. The major version of the
|
||||
client corresponds to the major version of Zitadel it is designed to work with. For example,
|
||||
v2.x.x of the client is built for and tested against Zitadel v2, ensuring a predictable and stable integration.
|
||||
|
||||
### Resources
|
||||
|
||||
- [GitHub Repository](https://github.com/zitadel/client-python): For source code, examples, and to report issues.
|
||||
- [PyPI Package](https://pypi.org/project/zitadel-client): The official package artifact for pip.
|
||||
|
200
docs/docs/sdk-examples/client-libraries/ruby.mdx
Normal file
@@ -0,0 +1,200 @@
|
||||
---
|
||||
title: Ruby Client
|
||||
sidebar_label: 'Ruby Client'
|
||||
---
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px">
|
||||
<img width="100px" src="/docs/img/tech/ruby.svg" alt="ruby logo"/>
|
||||
</td>
|
||||
<td>
|
||||
This guide covers the official Zitadel Management API Client for Ruby (3.1+), which allows you to programmatically manage resources in your Zitadel instance.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
:::info
|
||||
**This is a Management API Client, not an Authentication SDK.**
|
||||
|
||||
This library is designed for server-to-server communication to manage your Zitadel instance (e.g., creating users, managing projects, and updating settings). It is **not** intended for handling end-user login flows in your web application. For user authentication, you should use a standard OIDC library with your Ruby framework of choice.
|
||||
:::
|
||||
|
||||
The Zitadel Ruby Client provides an idiomatic way to access the full gamut of Zitadel's v2 Management APIs from your Ruby backend.
|
||||
|
||||
> Please be aware that this client library is currently in an **incubating stage**.
|
||||
While it is available for use, the API and its functionality may evolve, potentially introducing
|
||||
breaking changes in future updates. We advise caution when considering it for production environments.
|
||||
|
||||
### Installation
|
||||
|
||||
You can add the client library to your project using RubyGems. Add this line to your application's Gemfile:
|
||||
|
||||
```ruby
|
||||
gem install zitadel-client --pre
|
||||
```
|
||||
|
||||
### Using the SDK
|
||||
|
||||
Your SDK offers three ways to authenticate with Zitadel. Each method has its
|
||||
own benefits—choose the one that fits your situation best.
|
||||
|
||||
#### 1. Private Key JWT Authentication
|
||||
|
||||
**What is it?**
|
||||
You use a JSON Web Token (JWT) that you sign with a private key stored in a
|
||||
JSON file. This process creates a secure token.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Best for production:** It offers strong security.
|
||||
- **Advanced control:** You can adjust token settings like expiration.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Save your private key in a JSON file.
|
||||
2. Use the provided method to create an authenticator.
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
require 'zitadel-client'
|
||||
require 'securerandom'
|
||||
|
||||
client = Zitadel::Client::Zitadel.with_private_key("https://example.us1.zitadel.cloud", "path/to/jwt-key.json")
|
||||
|
||||
begin
|
||||
response = client.users.add_human_user(
|
||||
Zitadel::Client::UserServiceAddHumanUserRequest.new(
|
||||
username: SecureRandom.hex,
|
||||
profile: Zitadel::Client::UserServiceSetHumanProfile.new(
|
||||
given_name: 'John',
|
||||
family_name: 'Doe'
|
||||
),
|
||||
email: Zitadel::Client::UserServiceSetHumanEmail.new(
|
||||
email: "john.doe@example.com"
|
||||
)
|
||||
)
|
||||
)
|
||||
puts "User created: #{response}"
|
||||
rescue StandardError => e
|
||||
puts "Error: #{e.message}"
|
||||
end
|
||||
```
|
||||
|
||||
#### 2. Client Credentials Grant
|
||||
|
||||
**What is it?**
|
||||
This method uses a client ID and client secret to get a secure access token,
|
||||
which is then used to authenticate.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Simple and straightforward:** Good for server-to-server communication.
|
||||
- **Trusted environments:** Use it when both servers are owned or trusted.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Provide your client ID and client secret.
|
||||
2. Use the provided method to create an authenticator.
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
require 'zitadel-client'
|
||||
require 'securerandom'
|
||||
|
||||
client = Zitadel::Client::Zitadel.with_client_credentials("https://example.us1.zitadel.cloud", "id", "secret")
|
||||
|
||||
begin
|
||||
response = client.users.add_human_user(
|
||||
Zitadel::Client::UserServiceAddHumanUserRequest.new(
|
||||
username: SecureRandom.hex,
|
||||
profile: Zitadel::Client::UserServiceSetHumanProfile.new(
|
||||
given_name: 'John',
|
||||
family_name: 'Doe'
|
||||
),
|
||||
email: Zitadel::Client::UserServiceSetHumanEmail.new(
|
||||
email: "john.doe@example.com"
|
||||
)
|
||||
)
|
||||
)
|
||||
puts "User created: #{response}"
|
||||
rescue StandardError => e
|
||||
puts "Error: #{e.message}"
|
||||
end
|
||||
```
|
||||
|
||||
#### 3. Personal Access Tokens (PATs)
|
||||
|
||||
**What is it?**
|
||||
A Personal Access Token (PAT) is a pre-generated token that you can use to
|
||||
authenticate without exchanging credentials every time.
|
||||
|
||||
**When should you use it?**
|
||||
|
||||
- **Easy to use:** Great for development or testing scenarios.
|
||||
- **Quick setup:** No need for dynamic token generation.
|
||||
|
||||
**How do you use it?**
|
||||
|
||||
1. Obtain a valid personal access token from your account.
|
||||
2. Use the provided method to create an authenticator.
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
require 'zitadel-client'
|
||||
require 'securerandom'
|
||||
|
||||
client = Zitadel::Client::Zitadel.with_access_token("https://example.us1.zitadel.cloud", "token")
|
||||
|
||||
begin
|
||||
response = client.users.add_human_user(
|
||||
Zitadel::Client::UserServiceAddHumanUserRequest.new(
|
||||
username: SecureRandom.hex,
|
||||
profile: Zitadel::Client::UserServiceSetHumanProfile.new(
|
||||
given_name: 'John',
|
||||
family_name: 'Doe'
|
||||
),
|
||||
email: Zitadel::Client::UserServiceSetHumanEmail.new(
|
||||
email: "john.doe@example.com"
|
||||
)
|
||||
)
|
||||
)
|
||||
puts "User created: #{response}"
|
||||
rescue StandardError => e
|
||||
puts "Error: #{e.message}"
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Choose the authentication method that best suits your needs based on your
|
||||
environment and security requirements. For more details, please refer to the
|
||||
[Zitadel documentation on authenticating service users](https://zitadel.com/docs/guides/integrate/service-users/authenticate-service-users).
|
||||
|
||||
### Debugging
|
||||
|
||||
The SDK supports debug logging, which can be enabled for troubleshooting
|
||||
and debugging purposes. You can enable debug logging by setting the `debug`
|
||||
flag to `true` when initializing the `Zitadel` client, like this:
|
||||
|
||||
```ruby
|
||||
zitadel = zitadel.Zitadel("your-zitadel-base-url", 'your-valid-token', lambda config: config.debug = True)
|
||||
```
|
||||
|
||||
When enabled, the SDK will log additional information, such as HTTP request
|
||||
and response details, which can be useful for identifying issues in the
|
||||
integration or troubleshooting unexpected behavior.
|
||||
|
||||
### Versioning
|
||||
|
||||
The client library's versioning is aligned with the Zitadel core project. The major version of the
|
||||
client corresponds to the major version of Zitadel it is designed to work with. For example,
|
||||
v2.x.x of the client is built for and tested against Zitadel v2, ensuring a predictable and stable integration.
|
||||
|
||||
### Resources
|
||||
|
||||
- [GitHub Repository](https://github.com/zitadel/client-ruby): For source code, examples, and to report issues.
|
||||
- [RubyGems Package](https://rubygems.org/gems/zitadel-client): The official package artifact for RubyGems.
|
@@ -19,9 +19,17 @@ We provide this list for informational purposes and to foster community engageme
|
||||
|
||||
import { Frameworks } from "../../src/components/frameworks";
|
||||
|
||||
## Clients
|
||||
|
||||
<Frameworks filter={(framework) => framework.client === true } />
|
||||
|
||||
## SDKs
|
||||
|
||||
<Frameworks filter={(framework) => framework.sdk === true } />
|
||||
|
||||
## Resources
|
||||
|
||||
<Frameworks />
|
||||
<Frameworks filter={(framework) => framework.client === false || framework.client == null} />
|
||||
|
||||
To further streamline your setup, simply visit the console in ZITADEL where you can select one of the languages or frameworks. This will allow you to instantly set up the configuration for that specific sample in ZITADEL, ensuring you have everything you need to get started right away.
|
||||
|
||||
|
@@ -1,127 +1,169 @@
|
||||
[
|
||||
{
|
||||
"id": "angular",
|
||||
"title": "Angular",
|
||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||
"imgSrcLight": "/docs/img/tech/angular.svg",
|
||||
"imgSrcDark": "/docs/img/tech/angular.svg",
|
||||
"docsLink": "/docs/sdk-examples/angular"
|
||||
},
|
||||
{
|
||||
"id": "flutter",
|
||||
"title": "Flutter",
|
||||
"imgSrcDark": "/docs/img/tech/flutter.svg",
|
||||
"docsLink": "/docs/sdk-examples/flutter"
|
||||
},
|
||||
{
|
||||
"title": "Go",
|
||||
"imgSrcDark": "/docs/img/tech/golang.svg",
|
||||
"docsLink": "/docs/sdk-examples/go"
|
||||
},
|
||||
{
|
||||
"id": "java",
|
||||
"title": "Java",
|
||||
"imgSrcDark": "/docs/img/tech/java.svg",
|
||||
"docsLink": "/docs/sdk-examples/java"
|
||||
},
|
||||
{
|
||||
"title": "NestJS",
|
||||
"imgSrcDark": "/docs/img/tech/nestjs.svg",
|
||||
"docsLink": "/docs/sdk-examples/nestjs"
|
||||
},
|
||||
{
|
||||
"id": "next",
|
||||
"title": "Next.js",
|
||||
"imgSrcDark": "/docs/img/tech/nextjs.svg",
|
||||
"imgSrcLight": "/docs/img/tech/nextjslight.svg",
|
||||
"docsLink": "/docs/sdk-examples/nextjs"
|
||||
},
|
||||
{
|
||||
"id": "django",
|
||||
"title": "Python Django",
|
||||
"imgSrcDark": "/docs/img/tech/django.png",
|
||||
"docsLink": "/docs/sdk-examples/python-django"
|
||||
},
|
||||
{
|
||||
"title": "Python Flask",
|
||||
"imgSrcDark": "/docs/img/tech/flask.svg",
|
||||
"imgSrcLight": "/docs/img/tech/flasklight.svg",
|
||||
"docsLink": "/docs/sdk-examples/python-flask"
|
||||
},
|
||||
{
|
||||
"id": "react",
|
||||
"title": "React",
|
||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||
"imgSrcDark": "/docs/img/tech/react.png",
|
||||
"docsLink": "/docs/sdk-examples/react"
|
||||
},
|
||||
{
|
||||
"id": "symfony",
|
||||
"title": "Symfony",
|
||||
"imgSrcDark": "/docs/img/tech/php.svg",
|
||||
"docsLink": "/docs/sdk-examples/symfony"
|
||||
},
|
||||
{
|
||||
"id": "vue",
|
||||
"title": "Vue.js",
|
||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||
"imgSrcDark": "/docs/img/tech/vue.svg",
|
||||
"docsLink": "/docs/sdk-examples/vue"
|
||||
},
|
||||
{
|
||||
"title": "Dart",
|
||||
"imgSrcDark": "/docs/img/tech/dart.svg",
|
||||
"docsLink": "https://github.com/smartive/zitadel-dart",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "Elixir",
|
||||
"imgSrcDark": "/docs/img/tech/elixir.svg",
|
||||
"docsLink": "https://github.com/maennchen/zitadel_api",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "FastAPI",
|
||||
"imgSrcDark": "/docs/img/tech/fastapi.svg",
|
||||
"docsLink": "https://github.com/cleanenergyexchange/fastapi-zitadel-auth",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "NextAuth",
|
||||
"imgSrcDark": "/docs/img/tech/nextjs.svg",
|
||||
"imgSrcLight": "/docs/img/tech/nextjslight.svg",
|
||||
"docsLink": "https://next-auth.js.org/providers/zitadel",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "Node.js",
|
||||
"imgSrcDark": "/docs/img/tech/nodejs.svg",
|
||||
"docsLink": "https://www.npmjs.com/package/@zitadel/node",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": ".Net",
|
||||
"imgSrcDark": "/docs/img/tech/dotnet.svg",
|
||||
"docsLink": "https://github.com/smartive/zitadel-net",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "Passport.js",
|
||||
"imgSrcDark": "/docs/img/tech/passportjs.svg",
|
||||
"docsLink": "https://github.com/buehler/node-passport-zitadel",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "Rust",
|
||||
"imgSrcLight": "/docs/img/tech/rust.svg",
|
||||
"imgSrcDark": "/docs/img/tech/rustlight.svg",
|
||||
"docsLink": "https://github.com/smartive/zitadel-rust",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "Pylon",
|
||||
"imgSrcDark": "/docs/img/tech/pylon.svg",
|
||||
"docsLink": "https://github.com/getcronit/pylon",
|
||||
"external": true
|
||||
}
|
||||
{
|
||||
"id": "client-php",
|
||||
"title": "PHP",
|
||||
"imgSrcDark": "/docs/img/tech/php.svg",
|
||||
"docsLink": "/docs/sdk-examples/client-libraries/php",
|
||||
"client": true
|
||||
},
|
||||
{
|
||||
"id": "client-java",
|
||||
"title": "Java",
|
||||
"imgSrcDark": "/docs/img/tech/java.svg",
|
||||
"docsLink": "/docs/sdk-examples/client-libraries/java",
|
||||
"client": true
|
||||
},
|
||||
{
|
||||
"id": "client-go",
|
||||
"title": "Go",
|
||||
"imgSrcDark": "/docs/img/tech/golang.svg",
|
||||
"docsLink": "/docs/sdk-examples/go",
|
||||
"client": true,
|
||||
"sdk": true
|
||||
},
|
||||
{
|
||||
"id": "client-ruby",
|
||||
"title": "Ruby",
|
||||
"imgSrcDark": "/docs/img/tech/ruby.svg",
|
||||
"docsLink": "/docs/sdk-examples/client-libraries/ruby",
|
||||
"client": true
|
||||
},
|
||||
{
|
||||
"id": "client-python",
|
||||
"title": "Python",
|
||||
"imgSrcDark": "/docs/img/tech/python.svg",
|
||||
"docsLink": "/docs/sdk-examples/client-libraries/python",
|
||||
"client": true
|
||||
},
|
||||
|
||||
{
|
||||
"id": "angular",
|
||||
"title": "Angular",
|
||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||
"imgSrcLight": "/docs/img/tech/angular.svg",
|
||||
"imgSrcDark": "/docs/img/tech/angular.svg",
|
||||
"docsLink": "/docs/sdk-examples/angular"
|
||||
},
|
||||
{
|
||||
"id": "flutter",
|
||||
"title": "Flutter",
|
||||
"imgSrcDark": "/docs/img/tech/flutter.svg",
|
||||
"docsLink": "/docs/sdk-examples/flutter"
|
||||
},
|
||||
{
|
||||
"title": "Go",
|
||||
"imgSrcDark": "/docs/img/tech/golang.svg",
|
||||
"docsLink": "/docs/sdk-examples/go"
|
||||
},
|
||||
{
|
||||
"id": "spring",
|
||||
"title": "Spring",
|
||||
"imgSrcDark": "/docs/img/tech/spring.svg",
|
||||
"docsLink": "/docs/sdk-examples/java"
|
||||
},
|
||||
{
|
||||
"title": "NestJS",
|
||||
"imgSrcDark": "/docs/img/tech/nestjs.svg",
|
||||
"docsLink": "/docs/sdk-examples/nestjs"
|
||||
},
|
||||
{
|
||||
"id": "next",
|
||||
"title": "Next.js",
|
||||
"imgSrcDark": "/docs/img/tech/nextjs.svg",
|
||||
"imgSrcLight": "/docs/img/tech/nextjslight.svg",
|
||||
"docsLink": "/docs/sdk-examples/nextjs"
|
||||
},
|
||||
{
|
||||
"id": "django",
|
||||
"title": "Python Django",
|
||||
"imgSrcDark": "/docs/img/tech/django.svg",
|
||||
"docsLink": "/docs/sdk-examples/python-django"
|
||||
},
|
||||
{
|
||||
"title": "Python Flask",
|
||||
"imgSrcDark": "/docs/img/tech/flask.svg",
|
||||
"imgSrcLight": "/docs/img/tech/flask.svg",
|
||||
"docsLink": "/docs/sdk-examples/python-flask"
|
||||
},
|
||||
{
|
||||
"id": "react",
|
||||
"title": "React",
|
||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||
"imgSrcDark": "/docs/img/tech/react.svg",
|
||||
"docsLink": "/docs/sdk-examples/react"
|
||||
},
|
||||
{
|
||||
"id": "symfony",
|
||||
"title": "Symfony",
|
||||
"imgSrcDark": "/docs/img/tech/symfony.svg",
|
||||
"docsLink": "/docs/sdk-examples/symfony"
|
||||
},
|
||||
{
|
||||
"id": "vue",
|
||||
"title": "Vue.js",
|
||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||
"imgSrcDark": "/docs/img/tech/vue.svg",
|
||||
"docsLink": "/docs/sdk-examples/vue"
|
||||
},
|
||||
{
|
||||
"title": "Dart",
|
||||
"imgSrcDark": "/docs/img/tech/dart.svg",
|
||||
"docsLink": "https://github.com/smartive/zitadel-dart",
|
||||
"external": true,
|
||||
"client": true,
|
||||
"sdk": true
|
||||
},
|
||||
{
|
||||
"title": "Elixir",
|
||||
"imgSrcDark": "/docs/img/tech/elixir.svg",
|
||||
"docsLink": "https://github.com/maennchen/zitadel_api",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "FastAPI",
|
||||
"imgSrcDark": "/docs/img/tech/fastapi.svg",
|
||||
"docsLink": "https://github.com/cleanenergyexchange/fastapi-zitadel-auth",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "NextAuth",
|
||||
"imgSrcDark": "/docs/img/tech/nextjs.svg",
|
||||
"imgSrcLight": "/docs/img/tech/nextjslight.svg",
|
||||
"docsLink": "https://next-auth.js.org/providers/zitadel",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "Node.js",
|
||||
"imgSrcDark": "/docs/img/tech/nodejs.svg",
|
||||
"docsLink": "https://www.npmjs.com/package/@zitadel/node",
|
||||
"external": true,
|
||||
"client": true
|
||||
},
|
||||
{
|
||||
"title": ".Net",
|
||||
"imgSrcDark": "/docs/img/tech/dotnet.svg",
|
||||
"docsLink": "https://github.com/smartive/zitadel-net",
|
||||
"external": true,
|
||||
"client": true
|
||||
},
|
||||
{
|
||||
"title": "Passport.js",
|
||||
"imgSrcDark": "/docs/img/tech/passportjs.svg",
|
||||
"docsLink": "https://github.com/buehler/node-passport-zitadel",
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "Rust",
|
||||
"imgSrcLight": "/docs/img/tech/rust.svg",
|
||||
"imgSrcDark": "/docs/img/tech/rustlight.svg",
|
||||
"docsLink": "https://github.com/smartive/zitadel-rust",
|
||||
"client": true,
|
||||
"external": true
|
||||
},
|
||||
{
|
||||
"title": "Pylon",
|
||||
"imgSrcDark": "/docs/img/tech/pylon.svg",
|
||||
"docsLink": "https://github.com/getcronit/pylon",
|
||||
"external": true
|
||||
}
|
||||
]
|
||||
|
@@ -74,7 +74,6 @@ module.exports = {
|
||||
{
|
||||
type: "category",
|
||||
label: "Examples & SDKs",
|
||||
link: { type: "doc", id: "sdk-examples/introduction" },
|
||||
items: [
|
||||
{
|
||||
type: "autogenerated",
|
||||
|
@@ -2,20 +2,23 @@ import React from "react";
|
||||
import { Tile } from "./tile";
|
||||
import frameworks from "../../frameworks.json";
|
||||
|
||||
export function Frameworks({}) {
|
||||
return (
|
||||
<div className="tile-wrapper">
|
||||
{frameworks.map((framework) => {
|
||||
return (
|
||||
<Tile
|
||||
title={framework.title}
|
||||
imageSource={framework.imgSrcDark}
|
||||
imageSourceLight={framework.imgSrcLight}
|
||||
link={framework.docsLink}
|
||||
external={framework.external}
|
||||
></Tile>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
export function Frameworks({ filter }) {
|
||||
const filteredFrameworks = frameworks.filter((framework) => {
|
||||
return filter ? filter(framework) : true;
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="tile-wrapper">
|
||||
{filteredFrameworks.map((framework) => (
|
||||
<Tile
|
||||
key={framework.id || framework.title}
|
||||
title={framework.title}
|
||||
imageSource={framework.imgSrcDark}
|
||||
imageSourceLight={framework.imgSrcLight}
|
||||
link={framework.docsLink}
|
||||
external={framework.external}
|
||||
></Tile>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
10
docs/static/img/tech/django.svg
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<rect fill="#092E20" x="0" y="0" width="256" height="256" rx="28">
|
||||
|
||||
</rect>
|
||||
<path d="M186.377012,94.197636 L186.377012,160.424478 C186.377012,183.243286 184.707519,194.187745 179.699037,203.649406 C175.060358,212.741266 168.937684,218.490548 156.323731,224.798721 L129.794937,212.183571 C142.410087,206.247593 148.531564,201.05481 152.427049,193.074749 C156.509231,184.91278 157.808923,175.451119 157.808923,150.593015 L157.808923,94.197636 L186.377012,94.197636 Z M140.928486,50.0787207 L140.928486,182.316986 C126.272844,185.099476 115.512688,186.212472 103.826231,186.212472 C68.9487718,186.212472 50.7686431,170.445031 50.7686431,140.205054 C50.7686431,111.079269 70.0629644,92.1583404 99.9295492,92.1583404 C104.567032,92.1583404 108.091519,92.5281423 112.359199,93.6411381 L112.359199,50.0787207 L140.928486,50.0787207 Z M102.713236,115.160254 C88.243093,115.160254 79.8944275,124.065418 79.8944275,139.647359 C79.8944275,154.860696 87.8720944,163.208164 102.527736,163.208164 C105.680028,163.208164 108.278215,163.022665 112.359199,162.467364 L112.359199,116.643052 C109.020212,115.531253 106.237722,115.160254 102.713236,115.160254 Z M186.377012,50.2307105 L186.377012,79.5419941 L157.808923,79.5419941 L157.808923,50.2307105 L186.377012,50.2307105 Z" fill="#FFFFFD">
|
||||
|
||||
</path>
|
After Width: | Height: | Size: 1.6 KiB |
5
docs/static/img/tech/flask.svg
vendored
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
63
docs/static/img/tech/golang.svg
vendored
@@ -1,55 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 205.4 76.7" style="enable-background:new 0 0 205.4 76.7;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#00ACD7;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M15.5,23.2c-0.4,0-0.5-0.2-0.3-0.5l2.1-2.7c0.2-0.3,0.7-0.5,1.1-0.5h35.7c0.4,0,0.5,0.3,0.3,0.6l-1.7,2.6
|
||||
c-0.2,0.3-0.7,0.6-1,0.6L15.5,23.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M0.4,32.4c-0.4,0-0.5-0.2-0.3-0.5l2.1-2.7c0.2-0.3,0.7-0.5,1.1-0.5h45.6c0.4,0,0.6,0.3,0.5,0.6l-0.8,2.4
|
||||
c-0.1,0.4-0.5,0.6-0.9,0.6L0.4,32.4z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M24.6,41.6c-0.4,0-0.5-0.3-0.3-0.6l1.4-2.5c0.2-0.3,0.6-0.6,1-0.6h20c0.4,0,0.6,0.3,0.6,0.7L47.1,41
|
||||
c0,0.4-0.4,0.7-0.7,0.7L24.6,41.6z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g id="CXHf1q_3_">
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M128.4,21.4c-6.3,1.6-10.6,2.8-16.8,4.4c-1.5,0.4-1.6,0.5-2.9-1c-1.5-1.7-2.6-2.8-4.7-3.8
|
||||
c-6.3-3.1-12.4-2.2-18.1,1.5c-6.8,4.4-10.3,10.9-10.2,19c0.1,8,5.6,14.6,13.5,15.7c6.8,0.9,12.5-1.5,17-6.6
|
||||
c0.9-1.1,1.7-2.3,2.7-3.7c-3.6,0-8.1,0-19.3,0c-2.1,0-2.6-1.3-1.9-3c1.3-3.1,3.7-8.3,5.1-10.9c0.3-0.6,1-1.6,2.5-1.6
|
||||
c5.1,0,23.9,0,36.4,0c-0.2,2.7-0.2,5.4-0.6,8.1c-1.1,7.2-3.8,13.8-8.2,19.6c-7.2,9.5-16.6,15.4-28.5,17
|
||||
c-9.8,1.3-18.9-0.6-26.9-6.6c-7.4-5.6-11.6-13-12.7-22.2c-1.3-10.9,1.9-20.7,8.5-29.3c7.1-9.3,16.5-15.2,28-17.3
|
||||
c9.4-1.7,18.4-0.6,26.5,4.9c5.3,3.5,9.1,8.3,11.6,14.1C130,20.6,129.6,21.1,128.4,21.4z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st0" d="M161.5,76.7c-9.1-0.2-17.4-2.8-24.4-8.8c-5.9-5.1-9.6-11.6-10.8-19.3c-1.8-11.3,1.3-21.3,8.1-30.2
|
||||
c7.3-9.6,16.1-14.6,28-16.7c10.2-1.8,19.8-0.8,28.5,5.1c7.9,5.4,12.8,12.7,14.1,22.3c1.7,13.5-2.2,24.5-11.5,33.9
|
||||
c-6.6,6.7-14.7,10.9-24,12.8C166.8,76.3,164.1,76.4,161.5,76.7z M185.3,36.3c-0.1-1.3-0.1-2.3-0.3-3.3
|
||||
c-1.8-9.9-10.9-15.5-20.4-13.3c-9.3,2.1-15.3,8-17.5,17.4c-1.8,7.8,2,15.7,9.2,18.9c5.5,2.4,11,2.1,16.3-0.6
|
||||
C180.5,51.3,184.8,44.9,185.3,36.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 -160 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<path d="M292.533152,13.2950639 L293.657233,14.0455076 C306.869315,22.7704678 316.342129,34.7361275 322.574244,49.1946331 C324.069951,51.4381943 323.072813,52.6846171 320.081398,53.4324709 L315.017741,54.7277932 C303.571167,57.6768058 294.487155,60.1566573 283.191384,63.10567 L276.74841,64.7843862 C274.428264,65.3583626 273.787695,65.1170696 271.320433,62.3073717 L270.972336,61.9081465 C267.453024,57.9195933 264.816991,55.2559574 260.154613,52.878088 L259.255961,52.4353326 C243.551033,44.7075107 228.344673,46.9510719 214.135452,56.1746012 C197.184101,67.1431227 188.459141,83.3466202 188.708425,103.538671 C188.95771,123.481438 202.668362,139.93422 222.361843,142.67635 C239.313195,144.919911 253.522416,138.937081 264.740222,126.223568 C266.983783,123.481438 268.978059,120.490023 271.470905,117.000039 L223.358982,117.000039 C218.124006,117.000039 216.877583,113.759339 218.622575,109.521501 L219.486848,107.487264 C222.690544,100.033179 227.659682,89.3185944 230.887235,83.1925665 L231.591356,81.8743455 C232.452883,80.3801337 234.202861,78.3609287 237.568203,78.3609287 L317.791861,78.3603482 C321.394911,66.9456209 327.24084,56.159659 335.038473,45.9539335 C353.236247,22.0226141 375.17329,9.55838523 404.838154,4.32340907 C430.265181,-0.163713323 454.196501,2.32913245 475.884259,17.0369225 C495.577741,30.4982897 507.792685,48.6960639 511.033385,72.6273834 C515.271222,106.280802 505.549124,133.702105 482.365658,157.134856 C465.912876,173.836922 445.720825,184.306875 422.537359,189.043282 C415.806676,190.289704 409.075992,190.538989 402.594593,191.286843 C379.909697,190.788274 359.219077,184.306875 341.769156,169.3498 C329.496056,158.740849 321.041799,145.701725 316.840932,130.522127 C313.926247,136.409796 310.44016,142.04853 306.370746,147.412757 C288.422257,171.094792 264.989506,185.802582 235.324641,189.791135 C210.894753,193.031835 188.209856,188.295428 168.26709,173.338353 C149.820031,159.378417 139.350079,140.931358 136.607949,117.997177 C133.367249,90.8251575 141.344356,66.3952689 157.797138,44.9567952 C175.496343,21.7733295 198.929093,7.06553943 227.59682,1.8305633 C250.59563,-2.32879605 272.633891,0.235689133 292.533152,13.2950639 L292.533152,13.2950639 Z M411.120284,49.0171223 L410.322415,49.1946331 C387.138949,54.4296092 372.181875,69.1373993 366.697614,92.5701496 C362.210492,112.014347 371.683306,131.707829 389.631795,139.684935 C403.342447,145.667765 417.053099,144.919911 430.265181,138.189228 C449.958663,127.96856 460.6779,112.014347 461.924323,90.575873 C461.675038,87.3351735 461.675038,84.8423277 461.176469,82.3494819 C456.739764,57.9476028 434.511926,44.025432 411.120284,49.0171223 L411.120284,49.0171223 Z M116.415898,94.5644262 C117.413036,94.5644262 117.911605,95.3122799 117.911605,96.3094183 L117.413036,102.292248 C117.413036,103.289387 116.415898,104.03724 115.668044,104.03724 L61.3240061,103.787956 C60.3268678,103.787956 60.0775833,103.040102 60.5761524,102.292248 L64.0661365,96.0601337 C64.5647057,95.3122799 65.561844,94.5644262 66.5589823,94.5644262 L116.415898,94.5644262 Z M121.900159,71.6302451 C122.897297,71.6302451 123.395866,72.3780988 123.146581,73.1259525 L121.152305,79.1087824 C120.90302,80.1059207 119.905882,80.6044899 118.908744,80.6044899 L0.99713831,80.8537744 C0,80.8537744 -0.249284578,80.3552053 0.249284578,79.6073515 L5.48426071,72.8766679 C5.98282987,72.1288142 7.22925276,71.6302451 8.22639107,71.6302451 L121.900159,71.6302451 Z M134.862957,48.6960639 C135.860095,48.6960639 136.109379,49.4439176 135.61081,50.1917714 L131.372973,56.6731704 C130.874403,57.4210241 129.62798,58.1688779 128.880127,58.1688779 L38.6391096,57.9195933 C37.6419713,57.9195933 37.3926867,57.4210241 37.8912558,56.6731704 L43.126232,49.9424868 C43.6248011,49.1946331 44.871224,48.6960639 45.8683623,48.6960639 L134.862957,48.6960639 Z" fill="#00ACD7" fill-rule="nonzero">
|
||||
|
||||
</path>
|
||||
</g>
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.1 KiB |
52
docs/static/img/tech/java.svg
vendored
@@ -1,41 +1,11 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
|
||||
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
|
||||
width="233.549683248" height="428.174419289" viewBox="0 0 300 550" style="enable-background:new 0 0 300 550;" xml:space="preserve">
|
||||
|
||||
<path style="fill:#5382A1;" d="M285.104,430.945h-2.038v-1.14h5.486v1.14h-2.024v5.688h-1.424V430.945z M296.046,431.242h-0.032
|
||||
|
||||
l-2.019,5.392h-0.924l-2.006-5.392h-0.025v5.392h-1.342v-6.828h1.975l1.86,4.835l1.854-4.835h1.968v6.828h-1.31V431.242z"/>
|
||||
|
||||
<path style="fill:#5382A1;" d="M102.681,291.324c0,0-14.178,8.245,10.09,11.035c29.4,3.354,44.426,2.873,76.825-3.259
|
||||
|
||||
c0,0,8.518,5.341,20.414,9.967C137.38,340.195,45.634,307.264,102.681,291.324"/>
|
||||
|
||||
<path style="fill:#5382A1;" d="M93.806,250.704c0,0-15.902,11.771,8.384,14.283c31.406,3.24,56.208,3.505,99.125-4.759
|
||||
|
||||
c0,0,5.936,6.018,15.27,9.309C128.771,295.215,30.962,271.562,93.806,250.704"/>
|
||||
|
||||
<path style="fill:#F8981D;" d="M168.625,181.799c17.896,20.604-4.702,39.145-4.702,39.145s45.441-23.458,24.572-52.833
|
||||
|
||||
c-19.491-27.394-34.438-41.005,46.479-87.934C234.974,80.177,107.961,111.899,168.625,181.799"/>
|
||||
|
||||
<path style="fill:#5382A1;" d="M264.684,321.369c0,0,10.492,8.645-11.555,15.333c-41.923,12.7-174.488,16.535-211.314,0.506
|
||||
|
||||
c-13.238-5.759,11.587-13.751,19.396-15.428c8.144-1.766,12.798-1.437,12.798-1.437c-14.722-10.371-95.157,20.364-40.857,29.166
|
||||
|
||||
C181.236,373.524,303.095,338.695,264.684,321.369"/>
|
||||
|
||||
<path style="fill:#5382A1;" d="M109.499,208.617c0,0-67.431,16.016-23.879,21.832c18.389,2.462,55.047,1.905,89.193-0.956
|
||||
|
||||
c27.906-2.354,55.927-7.359,55.927-7.359s-9.84,4.214-16.959,9.075c-68.475,18.009-200.756,9.631-162.674-8.79
|
||||
|
||||
C83.313,206.851,109.499,208.617,109.499,208.617"/>
|
||||
|
||||
<path style="fill:#5382A1;" d="M230.462,276.231c69.608-36.171,37.424-70.931,14.96-66.248c-5.506,1.146-7.961,2.139-7.961,2.139
|
||||
|
||||
s2.044-3.202,5.948-4.588c44.441-15.624,78.619,46.081-14.346,70.52C229.063,278.055,230.14,277.092,230.462,276.231"/>
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.0497 8.44062C22.6378 3.32607 19.2566 0 19.2566 0C19.7598 5.28738 13.813 6.53583 12.2189 10.1692C11.1312 12.6485 12.9638 14.8193 16.0475 17.5554C15.7749 16.9494 15.3544 16.3606 14.9288 15.7645C13.4769 13.7313 11.9645 11.6132 16.0497 8.44062Z" fill="#E76F00"/>
|
||||
<path d="M17.1015 18.677C17.1015 18.677 19.0835 17.0779 17.5139 15.3008C12.1931 9.27186 23.3333 6.53583 23.3333 6.53583C16.5317 9.8125 17.5471 11.7574 19.2567 14.1202C21.0871 16.6538 17.1015 18.677 17.1015 18.677Z" fill="#E76F00"/>
|
||||
<path d="M22.937 23.4456C29.0423 20.3258 26.2195 17.3278 24.2492 17.7317C23.7662 17.8305 23.5509 17.9162 23.5509 17.9162C23.5509 17.9162 23.7302 17.64 24.0726 17.5204C27.9705 16.1729 30.9682 21.4949 22.8143 23.6028C22.8143 23.6029 22.9088 23.5198 22.937 23.4456Z" fill="#5382A1"/>
|
||||
<path d="M10.233 19.4969C6.41312 18.9953 12.3275 17.6139 12.3275 17.6139C12.3275 17.6139 10.0307 17.4616 7.20592 18.8043C3.86577 20.3932 15.4681 21.1158 21.474 19.5625C22.0984 19.1432 22.9614 18.7798 22.9614 18.7798C22.9614 18.7798 20.5037 19.2114 18.0561 19.4145C15.0612 19.6612 11.8459 19.7093 10.233 19.4969Z" fill="#5382A1"/>
|
||||
<path d="M11.6864 22.4758C9.55624 22.2592 10.951 21.2439 10.951 21.2439C5.43898 23.0429 14.0178 25.083 21.7199 22.8682C20.9012 22.5844 20.3806 22.0653 20.3806 22.0653C16.6163 22.7781 14.441 22.7553 11.6864 22.4758Z" fill="#5382A1"/>
|
||||
<path d="M12.6145 25.6991C10.486 25.4585 11.7295 24.7474 11.7295 24.7474C6.72594 26.1222 14.7729 28.9625 21.1433 26.2777C20.0999 25.8787 19.3528 25.4181 19.3528 25.4181C16.5111 25.9469 15.1931 25.9884 12.6145 25.6991Z" fill="#5382A1"/>
|
||||
<path d="M25.9387 27.3388C25.9387 27.3388 26.8589 28.0844 24.9252 28.6612C21.2481 29.7566 9.62093 30.0874 6.39094 28.7049C5.22984 28.2082 7.40723 27.5189 8.09215 27.3742C8.80646 27.2219 9.21466 27.2503 9.21466 27.2503C7.9234 26.3558 0.868489 29.0067 5.63111 29.7659C18.6195 31.8372 29.3077 28.8331 25.9387 27.3388Z" fill="#5382A1"/>
|
||||
<path d="M28 28.9679C27.7869 31.6947 18.7877 32.2683 12.9274 31.8994C9.10432 31.6583 8.33812 31.0558 8.32691 31.047C11.9859 31.6402 18.1549 31.7482 23.1568 30.8225C27.5903 30.0016 28 28.9679 28 28.9679Z" fill="#5382A1"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 2.3 KiB |
9
docs/static/img/tech/nodejs.svg
vendored
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 3.4 KiB |
98
docs/static/img/tech/php.svg
vendored
@@ -1,96 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg height="383.5975" id="svg3430" version="1.1" viewBox="0 0 711.20123 383.5975" width="711.20123" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<title id="title3510">Official PHP Logo</title>
|
||||
<metadata id="metadata3436">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title>Official PHP Logo</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Colin Viebrock</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:description/>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title/>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/"/>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>Copyright Colin Viebrock 1997 - All rights reserved.</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:date>1997</dc:date>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs id="defs3434">
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath3444">
|
||||
<path d="M 11.52,162 C 11.52,81.677 135.307,16.561 288,16.561 l 0,0 c 152.693,0 276.481,65.116 276.481,145.439 l 0,0 c 0,80.322 -123.788,145.439 -276.481,145.439 l 0,0 C 135.307,307.439 11.52,242.322 11.52,162" id="path3446"/>
|
||||
</clipPath>
|
||||
<radialGradient cx="0" cy="0" fx="0" fy="0" gradientTransform="matrix(363.05789,0,0,-363.05789,177.52002,256.30713)" gradientUnits="userSpaceOnUse" id="radialGradient3452" r="1" spreadMethod="pad">
|
||||
<stop id="stop3454" offset="0" style="stop-opacity:1;stop-color:#aeb2d5"/>
|
||||
<stop id="stop3456" offset="0.3" style="stop-opacity:1;stop-color:#aeb2d5"/>
|
||||
<stop id="stop3458" offset="0.75" style="stop-opacity:1;stop-color:#484c89"/>
|
||||
<stop id="stop3460" offset="1" style="stop-opacity:1;stop-color:#484c89"/>
|
||||
</radialGradient>
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath3468">
|
||||
<path d="M 0,324 576,324 576,0 0,0 0,324 Z" id="path3470"/>
|
||||
</clipPath>
|
||||
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath3480">
|
||||
<path d="M 0,324 576,324 576,0 0,0 0,324 Z" id="path3482"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="g3438" transform="matrix(1.25,0,0,-1.25,-4.4,394.29875)">
|
||||
<g id="g3440">
|
||||
<g clip-path="url(#clipPath3444)" id="g3442">
|
||||
<g id="g3448">
|
||||
<g id="g3450">
|
||||
<path d="M 11.52,162 C 11.52,81.677 135.307,16.561 288,16.561 l 0,0 c 152.693,0 276.481,65.116 276.481,145.439 l 0,0 c 0,80.322 -123.788,145.439 -276.481,145.439 l 0,0 C 135.307,307.439 11.52,242.322 11.52,162" id="path3462" style="fill:url(#radialGradient3452);stroke:none"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="g3464">
|
||||
<g clip-path="url(#clipPath3468)" id="g3466">
|
||||
<g id="g3472" transform="translate(288,27.3594)">
|
||||
<path d="M 0,0 C 146.729,0 265.68,60.281 265.68,134.641 265.68,209 146.729,269.282 0,269.282 -146.729,269.282 -265.68,209 -265.68,134.641 -265.68,60.281 -146.729,0 0,0" id="path3474" style="fill:#777bb3;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="g3476">
|
||||
<g clip-path="url(#clipPath3480)" id="g3478">
|
||||
<g id="g3484" transform="translate(161.7344,145.3066)">
|
||||
<path d="m 0,0 c 12.065,0 21.072,2.225 26.771,6.611 5.638,4.341 9.532,11.862 11.573,22.353 1.903,9.806 1.178,16.653 -2.154,20.348 C 32.783,53.086 25.417,55 14.297,55 L -4.984,55 -15.673,0 0,0 Z m -63.063,-67.75 c -0.895,0 -1.745,0.4 -2.314,1.092 -0.57,0.691 -0.801,1.601 -0.63,2.48 L -37.679,81.573 C -37.405,82.982 -36.17,84 -34.734,84 L 26.32,84 C 45.508,84 59.79,78.79 68.767,68.513 77.792,58.182 80.579,43.741 77.05,25.592 75.614,18.198 73.144,11.331 69.709,5.183 66.27,-0.972 61.725,-6.667 56.198,-11.747 49.582,-17.939 42.094,-22.429 33.962,-25.071 25.959,-27.678 15.681,-29 3.414,-29 l -24.722,0 -7.06,-36.322 c -0.274,-1.41 -1.508,-2.428 -2.944,-2.428 l -31.751,0 z" id="path3486" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
|
||||
</g>
|
||||
<g id="g3488" transform="translate(159.2236,197.3071)">
|
||||
<path d="m 0,0 16.808,0 c 13.421,0 18.083,-2.945 19.667,-4.7 2.628,-2.914 3.124,-9.058 1.435,-17.767 C 36.012,-32.217 32.494,-39.13 27.452,-43.012 22.29,-46.986 13.898,-49 2.511,-49 L -9.523,-49 0,0 Z m 28.831,35 -61.055,0 c -2.872,0 -5.341,-2.036 -5.889,-4.855 l -28.328,-145.751 c -0.342,-1.759 0.12,-3.578 1.259,-4.961 1.14,-1.383 2.838,-2.183 4.63,-2.183 l 31.75,0 c 2.873,0 5.342,2.036 5.89,4.855 l 6.588,33.895 22.249,0 c 12.582,0 23.174,1.372 31.479,4.077 8.541,2.775 16.399,7.48 23.354,13.984 5.752,5.292 10.49,11.232 14.08,17.657 3.591,6.427 6.171,13.594 7.668,21.302 3.715,19.104 0.697,34.402 -8.969,45.466 C 63.965,29.444 48.923,35 28.831,35 m -45.633,-90 19.313,0 c 12.801,0 22.336,2.411 28.601,7.234 6.266,4.824 10.492,12.875 12.688,24.157 2.101,10.832 1.144,18.476 -2.871,22.929 C 36.909,3.773 28.87,6 16.808,6 L -4.946,6 -16.802,-55 M 28.831,29 C 47.198,29 60.597,24.18 69.019,14.539 77.44,4.898 79.976,-8.559 76.616,-25.836 75.233,-32.953 72.894,-39.46 69.601,-45.355 66.304,-51.254 61.999,-56.648 56.679,-61.539 50.339,-67.472 43.296,-71.7 35.546,-74.218 27.796,-76.743 17.925,-78 5.925,-78 l -27.196,0 -7.531,-38.75 -31.75,0 28.328,145.75 61.055,0" id="path3490" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
|
||||
</g>
|
||||
<g id="g3492" transform="translate(311.583,116.3066)">
|
||||
<path d="m 0,0 c -0.896,0 -1.745,0.4 -2.314,1.092 -0.571,0.691 -0.802,1.6 -0.631,2.48 L 9.586,68.061 C 10.778,74.194 10.484,78.596 8.759,80.456 7.703,81.593 4.531,83.5 -4.848,83.5 L -27.55,83.5 -43.305,2.428 C -43.579,1.018 -44.814,0 -46.25,0 l -31.5,0 c -0.896,0 -1.745,0.4 -2.315,1.092 -0.57,0.691 -0.801,1.601 -0.63,2.48 l 28.328,145.751 c 0.274,1.409 1.509,2.427 2.945,2.427 l 31.5,0 c 0.896,0 1.745,-0.4 2.315,-1.091 0.57,-0.692 0.801,-1.601 0.63,-2.481 L -21.813,113 2.609,113 c 18.605,0 31.221,-3.28 38.569,-10.028 7.49,-6.884 9.827,-17.891 6.947,-32.719 L 34.945,2.428 C 34.671,1.018 33.437,0 32,0 L 0,0 Z" id="path3494" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
|
||||
</g>
|
||||
<g id="g3496" transform="translate(293.6611,271.0571)">
|
||||
<path d="m 0,0 -31.5,0 c -2.873,0 -5.342,-2.036 -5.89,-4.855 l -28.328,-145.751 c -0.342,-1.759 0.12,-3.578 1.26,-4.961 1.14,-1.383 2.838,-2.183 4.63,-2.183 l 31.5,0 c 2.872,0 5.342,2.036 5.89,4.855 l 15.283,78.645 20.229,0 c 9.363,0 11.328,-2 11.407,-2.086 0.568,-0.611 1.315,-3.441 0.082,-9.781 l -12.531,-64.489 c -0.342,-1.759 0.12,-3.578 1.26,-4.961 1.14,-1.383 2.838,-2.183 4.63,-2.183 l 32,0 c 2.872,0 5.342,2.036 5.89,4.855 l 13.179,67.825 c 3.093,15.921 0.447,27.864 -7.861,35.5 -7.928,7.281 -21.208,10.82 -40.599,10.82 l -20.784,0 6.143,31.605 C 6.231,-5.386 5.77,-3.566 4.63,-2.184 3.49,-0.801 1.792,0 0,0 m 0,-6 -7.531,-38.75 28.062,0 c 17.657,0 29.836,-3.082 36.539,-9.238 6.703,-6.16 8.711,-16.141 6.032,-29.938 l -13.18,-67.824 -32,0 12.531,64.488 c 1.426,7.336 0.902,12.34 -1.574,15.008 -2.477,2.668 -7.746,4.004 -15.805,4.004 l -25.176,0 -16.226,-83.5 -31.5,0 L -31.5,-6 0,-6" id="path3498" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
|
||||
</g>
|
||||
<g id="g3500" transform="translate(409.5498,145.3066)">
|
||||
<path d="m 0,0 c 12.065,0 21.072,2.225 26.771,6.611 5.638,4.34 9.532,11.861 11.574,22.353 1.903,9.806 1.178,16.653 -2.155,20.348 C 32.783,53.086 25.417,55 14.297,55 L -4.984,55 -15.673,0 0,0 Z m -63.062,-67.75 c -0.895,0 -1.745,0.4 -2.314,1.092 -0.57,0.691 -0.802,1.601 -0.631,2.48 L -37.679,81.573 C -37.404,82.982 -36.17,84 -34.733,84 L 26.32,84 C 45.509,84 59.79,78.79 68.768,68.513 77.793,58.183 80.579,43.742 77.051,25.592 75.613,18.198 73.144,11.331 69.709,5.183 66.27,-0.972 61.725,-6.667 56.198,-11.747 49.582,-17.939 42.094,-22.429 33.962,-25.071 25.959,-27.678 15.681,-29 3.414,-29 l -24.723,0 -7.057,-36.322 c -0.275,-1.41 -1.509,-2.428 -2.946,-2.428 l -31.75,0 z" id="path3502" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
|
||||
</g>
|
||||
<g id="g3504" transform="translate(407.0391,197.3071)">
|
||||
<path d="M 0,0 16.808,0 C 30.229,0 34.891,-2.945 36.475,-4.7 39.104,-7.614 39.6,-13.758 37.91,-22.466 36.012,-32.217 32.493,-39.13 27.452,-43.012 22.29,-46.986 13.898,-49 2.511,-49 L -9.522,-49 0,0 Z m 28.831,35 -61.054,0 c -2.872,0 -5.341,-2.036 -5.889,-4.855 L -66.44,-115.606 c -0.342,-1.759 0.12,-3.578 1.259,-4.961 1.14,-1.383 2.838,-2.183 4.63,-2.183 l 31.75,0 c 2.872,0 5.342,2.036 5.89,4.855 l 6.587,33.895 22.249,0 c 12.582,0 23.174,1.372 31.479,4.077 8.541,2.775 16.401,7.481 23.356,13.986 5.752,5.291 10.488,11.23 14.078,17.655 3.591,6.427 6.171,13.594 7.668,21.302 3.715,19.105 0.697,34.403 -8.969,45.467 C 63.965,29.444 48.924,35 28.831,35 m -45.632,-90 19.312,0 c 12.801,0 22.336,2.411 28.601,7.234 6.267,4.824 10.492,12.875 12.688,24.157 2.102,10.832 1.145,18.476 -2.871,22.929 C 36.909,3.773 28.87,6 16.808,6 L -4.946,6 -16.801,-55 M 28.831,29 C 47.198,29 60.597,24.18 69.019,14.539 77.441,4.898 79.976,-8.559 76.616,-25.836 75.233,-32.953 72.894,-39.46 69.601,-45.355 66.304,-51.254 61.999,-56.648 56.679,-61.539 50.339,-67.472 43.296,-71.7 35.546,-74.218 27.796,-76.743 17.925,-78 5.925,-78 l -27.196,0 -7.53,-38.75 -31.75,0 28.328,145.75 61.054,0" id="path3506" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><title>file_type_php3</title><path d="M7.6,13.791a2.352,2.352,0,0,1,1.745.483,1.916,1.916,0,0,1,.207,1.66,2.78,2.78,0,0,1-.918,1.748,3.375,3.375,0,0,1-2.07.529h-1.4L6.024,13.8ZM2,22.677H4.3l.545-2.8H6.812A7.049,7.049,0,0,0,8.956,19.6a4.06,4.06,0,0,0,1.53-.918A4.585,4.585,0,0,0,11.93,16.1a3.288,3.288,0,0,0-.55-2.922A3.671,3.671,0,0,0,8.47,12.129H4.057Z" style="fill:#8993be"/><path d="M13.617,9.323H15.9l-.553,2.8h2.031a3.956,3.956,0,0,1,2.645.669,2.213,2.213,0,0,1,.436,2.167l-.954,4.909H17.195l.908-4.667a1.267,1.267,0,0,0-.114-1.086,1.6,1.6,0,0,0-1.144-.286H15.022l-1.175,6.044H11.559Z" style="fill:#8993be"/><path d="M25.539,13.791a2.352,2.352,0,0,1,1.745.483,1.916,1.916,0,0,1,.207,1.66,2.78,2.78,0,0,1-.918,1.748,3.375,3.375,0,0,1-2.074.529H23.1l.858-4.416Zm-5.6,8.886h2.3l.545-2.8h1.968A7.049,7.049,0,0,0,26.9,19.6a4.06,4.06,0,0,0,1.53-.918A4.585,4.585,0,0,0,29.869,16.1a3.288,3.288,0,0,0-.55-2.922,3.671,3.671,0,0,0-2.909-1.046h-4.42Z" style="fill:#8993be"/></svg>
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 1.2 KiB |
16
docs/static/img/tech/python.svg
vendored
@@ -1 +1,15 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="240px" height="240px"><path fill="#0277BD" d="M24.047,5c-1.555,0.005-2.633,0.142-3.936,0.367c-3.848,0.67-4.549,2.077-4.549,4.67V14h9v2H15.22h-4.35c-2.636,0-4.943,1.242-5.674,4.219c-0.826,3.417-0.863,5.557,0,9.125C5.851,32.005,7.294,34,9.931,34h3.632v-5.104c0-2.966,2.686-5.896,5.764-5.896h7.236c2.523,0,5-1.862,5-4.377v-8.586c0-2.439-1.759-4.263-4.218-4.672C27.406,5.359,25.589,4.994,24.047,5z M19.063,9c0.821,0,1.5,0.677,1.5,1.502c0,0.833-0.679,1.498-1.5,1.498c-0.837,0-1.5-0.664-1.5-1.498C17.563,9.68,18.226,9,19.063,9z"/><path fill="#FFC107" d="M23.078,43c1.555-0.005,2.633-0.142,3.936-0.367c3.848-0.67,4.549-2.077,4.549-4.67V34h-9v-2h9.343h4.35c2.636,0,4.943-1.242,5.674-4.219c0.826-3.417,0.863-5.557,0-9.125C41.274,15.995,39.831,14,37.194,14h-3.632v5.104c0,2.966-2.686,5.896-5.764,5.896h-7.236c-2.523,0-5,1.862-5,4.377v8.586c0,2.439,1.759,4.263,4.218,4.672C19.719,42.641,21.536,43.006,23.078,43z M28.063,39c-0.821,0-1.5-0.677-1.5-1.502c0-0.833,0.679-1.498,1.5-1.498c0.837,0,1.5,0.664,1.5,1.498C29.563,38.32,28.899,39,28.063,39z"/></svg>
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.0164 2C10.8193 2 9.03825 3.72453 9.03825 5.85185V8.51852H15.9235V9.25926H5.97814C3.78107 9.25926 2 10.9838 2 13.1111L2 18.8889C2 21.0162 3.78107 22.7407 5.97814 22.7407H8.27322V19.4815C8.27322 17.3542 10.0543 15.6296 12.2514 15.6296H19.5956C21.4547 15.6296 22.9617 14.1704 22.9617 12.3704V5.85185C22.9617 3.72453 21.1807 2 18.9836 2H13.0164ZM12.0984 6.74074C12.8589 6.74074 13.4754 6.14378 13.4754 5.40741C13.4754 4.67103 12.8589 4.07407 12.0984 4.07407C11.3378 4.07407 10.7213 4.67103 10.7213 5.40741C10.7213 6.14378 11.3378 6.74074 12.0984 6.74074Z" fill="url(#paint0_linear_87_8204)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.9834 30C21.1805 30 22.9616 28.2755 22.9616 26.1482V23.4815L16.0763 23.4815L16.0763 22.7408L26.0217 22.7408C28.2188 22.7408 29.9998 21.0162 29.9998 18.8889V13.1111C29.9998 10.9838 28.2188 9.25928 26.0217 9.25928L23.7266 9.25928V12.5185C23.7266 14.6459 21.9455 16.3704 19.7485 16.3704L12.4042 16.3704C10.5451 16.3704 9.03809 17.8296 9.03809 19.6296L9.03809 26.1482C9.03809 28.2755 10.8192 30 13.0162 30H18.9834ZM19.9015 25.2593C19.1409 25.2593 18.5244 25.8562 18.5244 26.5926C18.5244 27.329 19.1409 27.9259 19.9015 27.9259C20.662 27.9259 21.2785 27.329 21.2785 26.5926C21.2785 25.8562 20.662 25.2593 19.9015 25.2593Z" fill="url(#paint1_linear_87_8204)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_87_8204" x1="12.4809" y1="2" x2="12.4809" y2="22.7407" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#327EBD"/>
|
||||
<stop offset="1" stop-color="#1565A7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_87_8204" x1="19.519" y1="9.25928" x2="19.519" y2="30" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFDA4B"/>
|
||||
<stop offset="1" stop-color="#F9C600"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.0 KiB |
5
docs/static/img/tech/react.svg
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18.6789 15.9759C18.6789 14.5415 17.4796 13.3785 16 13.3785C14.5206 13.3785 13.3211 14.5415 13.3211 15.9759C13.3211 17.4105 14.5206 18.5734 16 18.5734C17.4796 18.5734 18.6789 17.4105 18.6789 15.9759Z" fill="#53C1DE"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.7004 11.1537C25.2661 8.92478 25.9772 4.79148 23.4704 3.39016C20.9753 1.99495 17.7284 4.66843 16.0139 6.27318C14.3044 4.68442 10.9663 2.02237 8.46163 3.42814C5.96751 4.82803 6.73664 8.8928 7.3149 11.1357C4.98831 11.7764 1 13.1564 1 15.9759C1 18.7874 4.98416 20.2888 7.29698 20.9289C6.71658 23.1842 5.98596 27.1909 8.48327 28.5877C10.9973 29.9932 14.325 27.3945 16.0554 25.7722C17.7809 27.3864 20.9966 30.0021 23.4922 28.6014C25.9956 27.1963 25.3436 23.1184 24.7653 20.8625C27.0073 20.221 31 18.7523 31 15.9759C31 13.1835 26.9903 11.7923 24.7004 11.1537ZM24.4162 19.667C24.0365 18.5016 23.524 17.2623 22.8971 15.9821C23.4955 14.7321 23.9881 13.5088 24.3572 12.3509C26.0359 12.8228 29.7185 13.9013 29.7185 15.9759C29.7185 18.07 26.1846 19.1587 24.4162 19.667ZM22.85 27.526C20.988 28.571 18.2221 26.0696 16.9478 24.8809C17.7932 23.9844 18.638 22.9422 19.4625 21.7849C20.9129 21.6602 22.283 21.4562 23.5256 21.1777C23.9326 22.7734 24.7202 26.4763 22.85 27.526ZM9.12362 27.5111C7.26143 26.47 8.11258 22.8946 8.53957 21.2333C9.76834 21.4969 11.1286 21.6865 12.5824 21.8008C13.4123 22.9332 14.2816 23.9741 15.1576 24.8857C14.0753 25.9008 10.9945 28.557 9.12362 27.5111ZM2.28149 15.9759C2.28149 13.874 5.94207 12.8033 7.65904 12.3326C8.03451 13.5165 8.52695 14.7544 9.12123 16.0062C8.51925 17.2766 8.01977 18.5341 7.64085 19.732C6.00369 19.2776 2.28149 18.0791 2.28149 15.9759ZM9.1037 4.50354C10.9735 3.45416 13.8747 6.00983 15.1159 7.16013C14.2444 8.06754 13.3831 9.1006 12.5603 10.2265C11.1494 10.3533 9.79875 10.5569 8.55709 10.8297C8.09125 9.02071 7.23592 5.55179 9.1037 4.50354ZM20.3793 11.5771C21.3365 11.6942 22.2536 11.85 23.1147 12.0406C22.8562 12.844 22.534 13.6841 22.1545 14.5453C21.6044 13.5333 21.0139 12.5416 20.3793 11.5771ZM16.0143 8.0481C16.6054 8.66897 17.1974 9.3623 17.7798 10.1145C16.5985 10.0603 15.4153 10.0601 14.234 10.1137C14.8169 9.36848 15.414 8.67618 16.0143 8.0481ZM9.8565 14.5444C9.48329 13.6862 9.16398 12.8424 8.90322 12.0275C9.75918 11.8418 10.672 11.69 11.623 11.5748C10.9866 12.5372 10.3971 13.5285 9.8565 14.5444ZM11.6503 20.4657C10.6679 20.3594 9.74126 20.2153 8.88556 20.0347C9.15044 19.2055 9.47678 18.3435 9.85796 17.4668C10.406 18.4933 11.0045 19.4942 11.6503 20.4657ZM16.0498 23.9915C15.4424 23.356 14.8365 22.6531 14.2448 21.8971C15.4328 21.9423 16.6231 21.9424 17.811 21.891C17.2268 22.6608 16.6369 23.3647 16.0498 23.9915ZM22.1667 17.4222C22.5677 18.3084 22.9057 19.1657 23.1742 19.9809C22.3043 20.1734 21.3652 20.3284 20.3757 20.4435C21.015 19.4607 21.6149 18.4536 22.1667 17.4222ZM18.7473 20.5941C16.9301 20.72 15.1016 20.7186 13.2838 20.6044C12.2509 19.1415 11.3314 17.603 10.5377 16.0058C11.3276 14.4119 12.2404 12.8764 13.2684 11.4158C15.0875 11.2825 16.9178 11.2821 18.7369 11.4166C19.7561 12.8771 20.6675 14.4086 21.4757 15.9881C20.6771 17.5812 19.7595 19.1198 18.7473 20.5941ZM22.8303 4.4666C24.7006 5.51254 23.8681 9.22726 23.4595 10.8426C22.2149 10.5641 20.8633 10.3569 19.4483 10.2281C18.6239 9.09004 17.7698 8.05518 16.9124 7.15949C18.1695 5.98441 20.9781 3.43089 22.8303 4.4666Z" fill="#53C1DE"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
948
docs/static/img/tech/ruby.svg
vendored
Normal file
@@ -0,0 +1,948 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 198.13 197.58"
|
||||
overflow="visible"
|
||||
enable-background="new 0 0 198.13 197.58"
|
||||
xml:space="preserve"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="Logo-Ruby.svg"><metadata
|
||||
id="metadata3320"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs3489"><linearGradient
|
||||
id="XMLID_17_-9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="174.0737"
|
||||
y1="215.5488"
|
||||
x2="132.27631"
|
||||
y2="141.7533"><stop
|
||||
offset="0"
|
||||
style="stop-color:#FB7655"
|
||||
id="stop3272-4" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#FB7655"
|
||||
id="stop3274-5" /><stop
|
||||
offset="0.41"
|
||||
style="stop-color:#E42B1E"
|
||||
id="stop3276-1" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#990000"
|
||||
id="stop3278-0" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#990000"
|
||||
id="stop3280-3" /></linearGradient><linearGradient
|
||||
id="XMLID_18_-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="194.895"
|
||||
y1="153.5576"
|
||||
x2="141.0276"
|
||||
y2="117.4093"><stop
|
||||
offset="0"
|
||||
style="stop-color:#871101"
|
||||
id="stop3285-8" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#871101"
|
||||
id="stop3287-8" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#911209"
|
||||
id="stop3289-6" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#911209"
|
||||
id="stop3291-0" /></linearGradient><linearGradient
|
||||
id="XMLID_19_-4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="151.79539"
|
||||
y1="217.7852"
|
||||
x2="97.929703"
|
||||
y2="181.638"><stop
|
||||
offset="0"
|
||||
style="stop-color:#871101"
|
||||
id="stop3296-6" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#871101"
|
||||
id="stop3298-7" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#911209"
|
||||
id="stop3300-6" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#911209"
|
||||
id="stop3302-0" /></linearGradient><linearGradient
|
||||
id="XMLID_20_-9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="38.696301"
|
||||
y1="127.3906"
|
||||
x2="47.046902"
|
||||
y2="181.66141"><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3307-7" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3309-5" /><stop
|
||||
offset="0.23"
|
||||
style="stop-color:#E57252"
|
||||
id="stop3311-9" /><stop
|
||||
offset="0.46"
|
||||
style="stop-color:#DE3B20"
|
||||
id="stop3313-7" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#A60003"
|
||||
id="stop3315-8" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#A60003"
|
||||
id="stop3317-5" /></linearGradient><linearGradient
|
||||
id="XMLID_21_-3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="96.132797"
|
||||
y1="76.715302"
|
||||
x2="99.209602"
|
||||
y2="132.1021"><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3322-3" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3324-8" /><stop
|
||||
offset="0.23"
|
||||
style="stop-color:#E4714E"
|
||||
id="stop3326-3" /><stop
|
||||
offset="0.56"
|
||||
style="stop-color:#BE1A0D"
|
||||
id="stop3328-7" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3330-9" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3332-3" /></linearGradient><linearGradient
|
||||
id="XMLID_22_-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="147.103"
|
||||
y1="25.521"
|
||||
x2="156.3141"
|
||||
y2="65.216202"><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3337-8" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3339-7" /><stop
|
||||
offset="0.18"
|
||||
style="stop-color:#E46342"
|
||||
id="stop3341-4" /><stop
|
||||
offset="0.4"
|
||||
style="stop-color:#C82410"
|
||||
id="stop3343-1" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3345-9" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3347-0" /></linearGradient><linearGradient
|
||||
id="XMLID_23_-9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="118.9761"
|
||||
y1="11.5415"
|
||||
x2="158.66859"
|
||||
y2="-8.3048"><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3352-8" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3354-8" /><stop
|
||||
offset="0.54"
|
||||
style="stop-color:#C81F11"
|
||||
id="stop3356-5" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#BF0905"
|
||||
id="stop3358-8" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#BF0905"
|
||||
id="stop3360-4" /></linearGradient><linearGradient
|
||||
id="XMLID_24_-3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="3.9033"
|
||||
y1="113.5547"
|
||||
x2="7.1701999"
|
||||
y2="146.2628"><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3365-7" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3367-1" /><stop
|
||||
offset="0.31"
|
||||
style="stop-color:#DE4024"
|
||||
id="stop3369-3" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#BF190B"
|
||||
id="stop3371-8" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#BF190B"
|
||||
id="stop3373-0" /></linearGradient><linearGradient
|
||||
id="XMLID_25_-9"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18.5557"
|
||||
y1="155.10451"
|
||||
x2="135.0152"
|
||||
y2="-2.8092999"><stop
|
||||
offset="0"
|
||||
style="stop-color:#BD0012"
|
||||
id="stop3380-7" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#BD0012"
|
||||
id="stop3382-9" /><stop
|
||||
offset="0.07"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3384-9" /><stop
|
||||
offset="0.17"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3386-3" /><stop
|
||||
offset="0.27"
|
||||
style="stop-color:#C82F1C"
|
||||
id="stop3388-2" /><stop
|
||||
offset="0.33"
|
||||
style="stop-color:#820C01"
|
||||
id="stop3390-4" /><stop
|
||||
offset="0.46"
|
||||
style="stop-color:#A31601"
|
||||
id="stop3392-3" /><stop
|
||||
offset="0.72"
|
||||
style="stop-color:#B31301"
|
||||
id="stop3394-7" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#E82609"
|
||||
id="stop3396-1" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#E82609"
|
||||
id="stop3398-2" /></linearGradient><linearGradient
|
||||
id="XMLID_26_-2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="99.074699"
|
||||
y1="171.0332"
|
||||
x2="52.817699"
|
||||
y2="159.61659"><stop
|
||||
offset="0"
|
||||
style="stop-color:#8C0C01"
|
||||
id="stop3403-0" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#8C0C01"
|
||||
id="stop3405-2" /><stop
|
||||
offset="0.54"
|
||||
style="stop-color:#990C00"
|
||||
id="stop3407-1" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#A80D0E"
|
||||
id="stop3409-7" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#A80D0E"
|
||||
id="stop3411-5" /></linearGradient><linearGradient
|
||||
id="XMLID_27_-1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="178.52589"
|
||||
y1="115.5146"
|
||||
x2="137.43269"
|
||||
y2="78.683998"><stop
|
||||
offset="0"
|
||||
style="stop-color:#7E110B"
|
||||
id="stop3416-7" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#7E110B"
|
||||
id="stop3418-4" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#9E0C00"
|
||||
id="stop3420-1" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#9E0C00"
|
||||
id="stop3422-7" /></linearGradient><linearGradient
|
||||
id="XMLID_28_-1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="193.6235"
|
||||
y1="47.937"
|
||||
x2="173.15421"
|
||||
y2="26.053801"><stop
|
||||
offset="0"
|
||||
style="stop-color:#79130D"
|
||||
id="stop3427-1" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#79130D"
|
||||
id="stop3429-1" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#9E120B"
|
||||
id="stop3431-7" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#9E120B"
|
||||
id="stop3433-0" /></linearGradient><radialGradient
|
||||
id="XMLID_29_-4"
|
||||
cx="143.8315"
|
||||
cy="79.388199"
|
||||
r="50.357601"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
offset="0"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3440-0" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3442-8" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#7E0E08"
|
||||
id="stop3444-5" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#7E0E08"
|
||||
id="stop3446-1" /></radialGradient><radialGradient
|
||||
id="XMLID_30_-6"
|
||||
cx="74.0923"
|
||||
cy="145.75101"
|
||||
r="66.943703"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
offset="0"
|
||||
style="stop-color:#A30C00"
|
||||
id="stop3451-6" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#A30C00"
|
||||
id="stop3453-2" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#800E08"
|
||||
id="stop3455-1" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#800E08"
|
||||
id="stop3457-9" /></radialGradient><linearGradient
|
||||
id="XMLID_31_-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="26.669901"
|
||||
y1="197.33591"
|
||||
x2="9.9886999"
|
||||
y2="140.742"><stop
|
||||
offset="0"
|
||||
style="stop-color:#8B2114"
|
||||
id="stop3462-4" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#8B2114"
|
||||
id="stop3464-8" /><stop
|
||||
offset="0.43"
|
||||
style="stop-color:#9E100A"
|
||||
id="stop3466-0" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#B3100C"
|
||||
id="stop3468-8" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#B3100C"
|
||||
id="stop3470-1" /></linearGradient><linearGradient
|
||||
id="XMLID_32_-0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="154.6411"
|
||||
y1="9.7979002"
|
||||
x2="192.039"
|
||||
y2="26.305901"><stop
|
||||
offset="0"
|
||||
style="stop-color:#B31000"
|
||||
id="stop3475-2" /><stop
|
||||
offset="0"
|
||||
style="stop-color:#B31000"
|
||||
id="stop3477-2" /><stop
|
||||
offset="0.44"
|
||||
style="stop-color:#910F08"
|
||||
id="stop3479-9" /><stop
|
||||
offset="0.99"
|
||||
style="stop-color:#791C12"
|
||||
id="stop3481-7" /><stop
|
||||
offset="1"
|
||||
style="stop-color:#791C12"
|
||||
id="stop3483-5" /></linearGradient><linearGradient
|
||||
y2="141.7533"
|
||||
x2="132.27631"
|
||||
y1="215.5488"
|
||||
x1="174.0737"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3448"
|
||||
xlink:href="#XMLID_17_-9"
|
||||
inkscape:collect="always" /></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1036"
|
||||
inkscape:window-height="1124"
|
||||
id="namedview3487"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.3412289"
|
||||
inkscape:cx="99.065005"
|
||||
inkscape:cy="98.790004"
|
||||
inkscape:window-x="882"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<linearGradient
|
||||
id="XMLID_17_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="174.0737"
|
||||
y1="215.5488"
|
||||
x2="132.2763"
|
||||
y2="141.7533">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FB7655"
|
||||
id="stop3272" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FB7655"
|
||||
id="stop3274" />
|
||||
<stop
|
||||
offset="0.41"
|
||||
style="stop-color:#E42B1E"
|
||||
id="stop3276" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#990000"
|
||||
id="stop3278" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#990000"
|
||||
id="stop3280" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_18_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="194.895"
|
||||
y1="153.5576"
|
||||
x2="141.0276"
|
||||
y2="117.4093">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#871101"
|
||||
id="stop3285" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#871101"
|
||||
id="stop3287" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#911209"
|
||||
id="stop3289" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#911209"
|
||||
id="stop3291" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_19_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="151.7954"
|
||||
y1="217.7852"
|
||||
x2="97.9297"
|
||||
y2="181.638">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#871101"
|
||||
id="stop3296" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#871101"
|
||||
id="stop3298" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#911209"
|
||||
id="stop3300" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#911209"
|
||||
id="stop3302" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_20_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="38.6963"
|
||||
y1="127.3906"
|
||||
x2="47.0469"
|
||||
y2="181.6614">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3307" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3309" />
|
||||
<stop
|
||||
offset="0.23"
|
||||
style="stop-color:#E57252"
|
||||
id="stop3311" />
|
||||
<stop
|
||||
offset="0.46"
|
||||
style="stop-color:#DE3B20"
|
||||
id="stop3313" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#A60003"
|
||||
id="stop3315" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#A60003"
|
||||
id="stop3317" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_21_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="96.1328"
|
||||
y1="76.7153"
|
||||
x2="99.2096"
|
||||
y2="132.1021">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3322" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3324" />
|
||||
<stop
|
||||
offset="0.23"
|
||||
style="stop-color:#E4714E"
|
||||
id="stop3326" />
|
||||
<stop
|
||||
offset="0.56"
|
||||
style="stop-color:#BE1A0D"
|
||||
id="stop3328" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3330" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3332" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_22_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="147.103"
|
||||
y1="25.521"
|
||||
x2="156.3141"
|
||||
y2="65.2162">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3337" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3339" />
|
||||
<stop
|
||||
offset="0.18"
|
||||
style="stop-color:#E46342"
|
||||
id="stop3341" />
|
||||
<stop
|
||||
offset="0.4"
|
||||
style="stop-color:#C82410"
|
||||
id="stop3343" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3345" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3347" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_23_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="118.9761"
|
||||
y1="11.5415"
|
||||
x2="158.6686"
|
||||
y2="-8.3048">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3352" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3354" />
|
||||
<stop
|
||||
offset="0.54"
|
||||
style="stop-color:#C81F11"
|
||||
id="stop3356" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#BF0905"
|
||||
id="stop3358" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#BF0905"
|
||||
id="stop3360" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_24_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="3.9033"
|
||||
y1="113.5547"
|
||||
x2="7.1702"
|
||||
y2="146.2628">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3365" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3367" />
|
||||
<stop
|
||||
offset="0.31"
|
||||
style="stop-color:#DE4024"
|
||||
id="stop3369" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#BF190B"
|
||||
id="stop3371" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#BF190B"
|
||||
id="stop3373" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_25_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18.5557"
|
||||
y1="155.1045"
|
||||
x2="135.0152"
|
||||
y2="-2.8093">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#BD0012"
|
||||
id="stop3380" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#BD0012"
|
||||
id="stop3382" />
|
||||
<stop
|
||||
offset="0.07"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3384" />
|
||||
<stop
|
||||
offset="0.17"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop3386" />
|
||||
<stop
|
||||
offset="0.27"
|
||||
style="stop-color:#C82F1C"
|
||||
id="stop3388" />
|
||||
<stop
|
||||
offset="0.33"
|
||||
style="stop-color:#820C01"
|
||||
id="stop3390" />
|
||||
<stop
|
||||
offset="0.46"
|
||||
style="stop-color:#A31601"
|
||||
id="stop3392" />
|
||||
<stop
|
||||
offset="0.72"
|
||||
style="stop-color:#B31301"
|
||||
id="stop3394" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#E82609"
|
||||
id="stop3396" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#E82609"
|
||||
id="stop3398" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_26_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="99.0747"
|
||||
y1="171.0332"
|
||||
x2="52.8177"
|
||||
y2="159.6166">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#8C0C01"
|
||||
id="stop3403" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#8C0C01"
|
||||
id="stop3405" />
|
||||
<stop
|
||||
offset="0.54"
|
||||
style="stop-color:#990C00"
|
||||
id="stop3407" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#A80D0E"
|
||||
id="stop3409" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#A80D0E"
|
||||
id="stop3411" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_27_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="178.5259"
|
||||
y1="115.5146"
|
||||
x2="137.4327"
|
||||
y2="78.684">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#7E110B"
|
||||
id="stop3416" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#7E110B"
|
||||
id="stop3418" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#9E0C00"
|
||||
id="stop3420" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#9E0C00"
|
||||
id="stop3422" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_28_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="193.6235"
|
||||
y1="47.937"
|
||||
x2="173.1542"
|
||||
y2="26.0538">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#79130D"
|
||||
id="stop3427" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#79130D"
|
||||
id="stop3429" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#9E120B"
|
||||
id="stop3431" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#9E120B"
|
||||
id="stop3433" />
|
||||
</linearGradient>
|
||||
|
||||
|
||||
<radialGradient
|
||||
id="XMLID_29_"
|
||||
cx="143.8315"
|
||||
cy="79.3882"
|
||||
r="50.3576"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3440" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#A80D00"
|
||||
id="stop3442" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#7E0E08"
|
||||
id="stop3444" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#7E0E08"
|
||||
id="stop3446" />
|
||||
</radialGradient>
|
||||
|
||||
<radialGradient
|
||||
id="XMLID_30_"
|
||||
cx="74.0923"
|
||||
cy="145.751"
|
||||
r="66.9437"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#A30C00"
|
||||
id="stop3451" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#A30C00"
|
||||
id="stop3453" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#800E08"
|
||||
id="stop3455" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#800E08"
|
||||
id="stop3457" />
|
||||
</radialGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_31_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="26.6699"
|
||||
y1="197.3359"
|
||||
x2="9.9887"
|
||||
y2="140.742">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#8B2114"
|
||||
id="stop3462" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#8B2114"
|
||||
id="stop3464" />
|
||||
<stop
|
||||
offset="0.43"
|
||||
style="stop-color:#9E100A"
|
||||
id="stop3466" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#B3100C"
|
||||
id="stop3468" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#B3100C"
|
||||
id="stop3470" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient
|
||||
id="XMLID_32_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="154.6411"
|
||||
y1="9.7979"
|
||||
x2="192.039"
|
||||
y2="26.3059">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#B31000"
|
||||
id="stop3475" />
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#B31000"
|
||||
id="stop3477" />
|
||||
<stop
|
||||
offset="0.44"
|
||||
style="stop-color:#910F08"
|
||||
id="stop3479" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
style="stop-color:#791C12"
|
||||
id="stop3481" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#791C12"
|
||||
id="stop3483" />
|
||||
</linearGradient>
|
||||
|
||||
<polygon
|
||||
style="fill:url(#linearGradient3448);fill-rule:evenodd"
|
||||
clip-rule="evenodd"
|
||||
points="153.5,130.41 40.38,197.58 186.849,187.641 198.13,39.95 "
|
||||
id="polygon3282" /><polygon
|
||||
style="fill:url(#XMLID_18_-7);fill-rule:evenodd"
|
||||
clip-rule="evenodd"
|
||||
points="187.089,187.54 174.5,100.65 140.209,145.93 "
|
||||
id="polygon3293" /><polygon
|
||||
style="fill:url(#XMLID_19_-4);fill-rule:evenodd"
|
||||
clip-rule="evenodd"
|
||||
points="187.259,187.54 95.03,180.3 40.87,197.391 "
|
||||
id="polygon3304" /><polygon
|
||||
style="fill:url(#XMLID_20_-9);fill-rule:evenodd"
|
||||
clip-rule="evenodd"
|
||||
points="41,197.41 64.04,121.93 13.34,132.771 "
|
||||
id="polygon3319" /><polygon
|
||||
style="fill:url(#XMLID_21_-3);fill-rule:evenodd"
|
||||
clip-rule="evenodd"
|
||||
points="140.2,146.18 119,63.14 58.33,120.01 "
|
||||
id="polygon3334" /><polygon
|
||||
style="fill:url(#XMLID_22_-7);fill-rule:evenodd"
|
||||
clip-rule="evenodd"
|
||||
points="193.32,64.31 135.97,17.47 120,69.1 "
|
||||
id="polygon3349" /><polygon
|
||||
style="fill:url(#XMLID_23_-9);fill-rule:evenodd"
|
||||
clip-rule="evenodd"
|
||||
points="166.5,0.77 132.77,19.41 111.49,0.52 "
|
||||
id="polygon3362" /><polygon
|
||||
style="fill:url(#XMLID_24_-3);fill-rule:evenodd"
|
||||
clip-rule="evenodd"
|
||||
points="0,158.09 14.13,132.32 2.7,101.62 "
|
||||
id="polygon3375" /><path
|
||||
style="fill:#ffffff;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 1.94,100.65 11.5,32.62 49.97,-11.211 57.05,-53.02 L 136.56,17.9 111.209,0 68.109,16.13 C 54.53,28.76 28.18,53.75 27.23,54.22 26.29,54.7 9.83,85.81 1.94,100.65 z"
|
||||
id="path3377" /><path
|
||||
style="fill:url(#XMLID_25_-9);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 42.32,42.05 c 29.43,-29.18 67.37,-46.42 81.93,-31.73 14.551,14.69 -0.88,50.39 -30.31,79.56 -29.43,29.17 -66.9,47.36 -81.45,32.67 -14.56,-14.68 0.4,-51.33 29.83,-80.5 z"
|
||||
id="path3400" /><path
|
||||
style="fill:url(#XMLID_26_-2);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 41,197.38 22.86,-75.72 75.92,24.39 C 112.33,171.79 81.8,193.55 41,197.38 z"
|
||||
id="path3413" /><path
|
||||
style="fill:url(#XMLID_27_-1);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 120.56,68.89 19.49,77.2 C 162.98,121.98 183.56,96.06 193.639,64 l -73.079,4.89 z"
|
||||
id="path3424" /><path
|
||||
style="fill:url(#XMLID_28_-1);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 193.44,64.39 c 7.8,-23.54 9.6,-57.31 -27.181,-63.58 l -30.18,16.67 57.361,46.91 z"
|
||||
id="path3435" /><path
|
||||
style="fill:#9e1209;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 0,157.75 c 1.08,38.851 29.11,39.43 41.05,39.771 L 13.47,133.11 0,157.75 z"
|
||||
id="path3437" /><path
|
||||
style="fill:url(#XMLID_29_-4);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 120.669,69.01 c 17.62,10.83 53.131,32.58 53.851,32.98 1.119,0.63 15.31,-23.93 18.53,-37.81 l -72.381,4.83 z"
|
||||
id="path3448" /><path
|
||||
style="fill:url(#XMLID_30_-6);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 63.83,121.66 30.56,58.96 c 18.07,-9.8 32.22,-21.74 45.18,-34.53 L 63.83,121.66 z"
|
||||
id="path3459" /><path
|
||||
style="fill:url(#XMLID_31_-6);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 13.35,133.19 -4.33,51.56 c 8.17,11.16 19.41,12.13 31.2,11.26 -8.53,-21.23 -25.57,-63.68 -26.87,-62.82 z"
|
||||
id="path3472" /><path
|
||||
style="fill:url(#XMLID_32_-0);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
clip-rule="evenodd"
|
||||
d="m 135.9,17.61 60.71,8.52 C 193.37,12.4 183.42,3.54 166.46,0.77 L 135.9,17.61 z"
|
||||
id="path3485" /></svg>
|
After Width: | Height: | Size: 23 KiB |
8
docs/static/img/tech/spring.svg
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
|
||||
<path d="M0 0h32v32H0z"/>
|
After Width: | Height: | Size: 1.1 KiB |
2
docs/static/img/tech/symfony.svg
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M 16 3 C 8.832 3 3 8.832 3 16 C 3 23.168 8.832 29 16 29 C 23.168 29 29 23.168 29 16 C 29 8.832 23.168 3 16 3 z M 16 5 C 22.065 5 27 9.935 27 16 C 27 22.065 22.065 27 16 27 C 9.935 27 5 22.065 5 16 C 5 9.935 9.935 5 16 5 z M 20.271484 10.076172 C 20.198484 10.078172 17.758172 9.941625 16.326172 14.140625 C 15.938172 13.821625 14.100406 11.630484 12.066406 13.146484 C 11.336406 13.692484 10.854172 14.993797 11.951172 16.216797 C 12.604172 16.915797 12.980594 17.192953 12.808594 17.751953 C 12.455594 18.899953 10.66775 18.373687 10.84375 17.804688 C 10.89575 17.634688 10.978938 17.631781 11.085938 17.300781 C 11.383938 16.324781 10.040953 15.847344 9.7519531 16.777344 C 9.5859531 17.319344 9.8434687 18.298562 11.230469 18.726562 C 12.854469 19.225562 14.228828 18.3405 14.423828 17.1875 C 14.547828 16.4655 14.221047 15.929281 13.623047 15.238281 L 13.136719 14.699219 C 12.841719 14.402219 12.739922 13.900625 13.044922 13.515625 C 13.301922 13.189625 13.668531 13.051844 14.269531 13.214844 C 15.146531 13.452844 15.537453 14.061734 16.189453 14.552734 C 16.142453 14.706734 15.804281 15.797937 15.488281 17.710938 C 15.022281 20.156938 14.665234 21.499531 13.740234 22.269531 C 13.554234 22.404531 13.287719 22.603188 12.886719 22.617188 C 12.811719 22.620187 12.342594 22.508766 12.808594 22.134766 C 13.395594 21.813766 13.077375 20.795219 12.234375 20.824219 C 11.854375 20.836219 11.276828 21.192656 11.298828 21.847656 C 11.320828 22.523656 11.950391 23.031047 12.900391 22.998047 C 13.408391 22.981047 14.541203 22.775266 15.658203 21.447266 C 17.193203 19.647266 17.485391 17.509797 17.900391 15.216797 C 19.891391 15.452797 20.876625 14.529797 20.890625 13.841797 C 20.911625 12.905797 19.81025 12.938672 19.65625 13.638672 C 19.58225 13.978672 20.174891 14.284984 19.712891 14.583984 C 19.385891 14.795984 18.798656 14.945219 17.972656 14.824219 C 18.369656 12.634219 18.709187 10.4875 20.242188 10.4375 C 20.347188 10.4315 20.729281 10.443312 20.738281 10.695312 C 20.743281 10.903312 20.476328 11.067875 20.486328 11.421875 C 20.501328 11.823875 20.806047 12.086313 21.248047 12.070312 C 21.839047 12.049312 22.008047 11.475687 21.998047 11.179688 C 21.973047 10.483688 21.240484 10.045172 20.271484 10.076172 z"/></svg>
|
After Width: | Height: | Size: 2.4 KiB |
4
docs/static/img/tech/vue.svg
vendored
@@ -1,2 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" viewBox="0 0 261.76 226.69" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)"><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-75.491l98.16-170.02 98.16 170.02z" fill="#41b883"/></g><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-36.227l58.896-102.01 58.896 102.01z" fill="#34495e"/></g></g></svg>
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 -17.5 256 256" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"><path d="M204.8 0H256L128 220.8 0 0h97.92L128 51.2 157.44 0h47.36z" fill="#41B883"/><path d="M0 0l128 220.8L256 0h-51.2L128 132.48 50.56 0H0z" fill="#41B883"/><path d="M50.56 0L128 133.12 204.8 0h-47.36L128 51.2 97.92 0H50.56z" fill="#35495E"/></svg>
|
Before Width: | Height: | Size: 467 B After Width: | Height: | Size: 500 B |
@@ -262,6 +262,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Пол
|
||||
Female: Женски пол
|
||||
Male: Мъжки
|
||||
@@ -305,6 +306,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Правила и условия
|
||||
TosConfirm: Приемам
|
||||
TosLinkText: TOS
|
||||
@@ -377,6 +379,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Упълномощаване на устройството
|
||||
UserCode:
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Pohlaví
|
||||
Female: Žena
|
||||
Male: Muž
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Obchodní podmínky
|
||||
TosConfirm: Souhlasím s
|
||||
TosLinkText: obchodními podmínkami
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Autorizace zařízení
|
||||
UserCode:
|
||||
|
@@ -265,6 +265,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Geschlecht
|
||||
Female: weiblich
|
||||
Male: männlich
|
||||
@@ -309,6 +310,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Allgemeine Geschäftsbedingungen und Datenschutz
|
||||
TosConfirm: Ich akzeptiere die
|
||||
TosLinkText: AGB
|
||||
@@ -387,6 +389,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Gerät verbinden
|
||||
UserCode:
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Gender
|
||||
Female: Female
|
||||
Male: Male
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Terms and conditions
|
||||
TosConfirm: I accept the
|
||||
TosLinkText: TOS
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Device Authorization
|
||||
UserCode:
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Género
|
||||
Female: Mujer
|
||||
Male: Hombre
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Términos y condiciones
|
||||
TosConfirm: Acepto los
|
||||
TosLinkText: TDS
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
|
||||
Footer:
|
||||
PoweredBy: Powered By
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Genre
|
||||
Female: Femme
|
||||
Male: Homme
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Termes et conditions
|
||||
TosConfirm: J'accepte les
|
||||
TosLinkText: TOS
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
|
||||
DeviceAuth:
|
||||
Title: Autorisation de l'appareil
|
||||
|
@@ -236,6 +236,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Nem
|
||||
Female: Nő
|
||||
Male: Férfi
|
||||
@@ -279,6 +280,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Felhasználási feltételek
|
||||
TosConfirm: Elfogadom a
|
||||
TosLinkText: TOS
|
||||
@@ -351,6 +353,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Eszköz engedélyezése
|
||||
UserCode:
|
||||
|
@@ -236,6 +236,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Jenis kelamin
|
||||
Female: Perempuan
|
||||
Male: Pria
|
||||
@@ -279,6 +280,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Syarat dan Ketentuan
|
||||
TosConfirm: Saya menerima itu
|
||||
TosLinkText: KL
|
||||
@@ -351,6 +353,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Otorisasi Perangkat
|
||||
UserCode:
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Genere
|
||||
Female: Femminile
|
||||
Male: Maschile
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Termini di servizio
|
||||
TosConfirm: Accetto i
|
||||
TosLinkText: Termini di servizio
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
|
||||
DeviceAuth:
|
||||
Title: Autorizzazione del dispositivo
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: 性別
|
||||
Female: 女性
|
||||
Male: 男性
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: 利用規約
|
||||
TosConfirm: 私は利用規約を承諾します。
|
||||
TosLinkText: TOS
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
|
||||
DeviceAuth:
|
||||
Title: デバイス認証
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: 성별
|
||||
Female: 여성
|
||||
Male: 남성
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: 동의사항
|
||||
TosConfirm: 이용 약관에 동의합니다.
|
||||
TosLinkText: 이용 약관
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: 기기 인증
|
||||
UserCode:
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Пол
|
||||
Female: Женски
|
||||
Male: Машки
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Правила и услови
|
||||
TosConfirm: Се согласувам со
|
||||
TosLinkText: правилата за користење
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
|
||||
DeviceAuth:
|
||||
Title: Овластување преку уред
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Geslacht
|
||||
Female: Vrouw
|
||||
Male: Man
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Algemene voorwaarden
|
||||
TosConfirm: Ik accepteer de
|
||||
TosLinkText: AV
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Apparaat Autorisatie
|
||||
UserCode:
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Płeć
|
||||
Female: Kobieta
|
||||
Male: Mężczyzna
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Warunki i zasady
|
||||
TosConfirm: Akceptuję
|
||||
TosLinkText: Warunki korzystania
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
|
||||
DeviceAuth:
|
||||
Title: Autoryzacja urządzenia
|
||||
|
@@ -262,6 +262,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Gênero
|
||||
Female: Feminino
|
||||
Male: Masculino
|
||||
@@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Termos e condições
|
||||
TosConfirm: Eu aceito os
|
||||
TosLinkText: termos de serviço
|
||||
@@ -384,6 +386,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
|
||||
DeviceAuth:
|
||||
Title: Autorização de dispositivo
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Gen
|
||||
Female: Femeie
|
||||
Male: Bărbat
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Termeni și condiții
|
||||
TosConfirm: Accept
|
||||
TosLinkText: TOS
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Autorizare dispozitiv
|
||||
UserCode:
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Пол
|
||||
Female: Женский
|
||||
Male: Мужской
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Условия использования
|
||||
TosConfirm: Я согласен с
|
||||
TosLinkText: Пользовательским соглашением
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
|
||||
DeviceAuth:
|
||||
Title: Авторизация устройства
|
||||
|
@@ -266,6 +266,7 @@ RegistrationUser:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
GenderLabel: Kön
|
||||
Female: Man
|
||||
Male: Kvinna
|
||||
@@ -310,6 +311,7 @@ ExternalRegistrationUserOverview:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
TosAndPrivacyLabel: Användarvillkor
|
||||
TosConfirm: Jag accepterar
|
||||
TosLinkText: Användarvillkoren
|
||||
@@ -388,6 +390,7 @@ ExternalNotFound:
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
Romanian: Română
|
||||
Turkish: Türkçe
|
||||
DeviceAuth:
|
||||
Title: Tillgång från hårdvaruenhet
|
||||
UserCode:
|
||||
|