stages/email: rework email templates (#7029)

rework email templates

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-10-02 16:04:40 +02:00 committed by GitHub
parent e40a0b1f8b
commit cb6dadbf94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 371 additions and 458 deletions

View File

@ -436,32 +436,39 @@ class NotificationTransport(SerializerModel):
def send_email(self, notification: "Notification") -> list[str]:
"""Send notification via global email configuration"""
subject = "authentik Notification: "
key_value = {
"user_email": notification.user.email,
"user_username": notification.user.username,
subject_prefix = "authentik Notification: "
context = {
"key_value": {
"user_email": notification.user.email,
"user_username": notification.user.username,
},
"body": notification.body,
"title": "",
}
if notification.event and notification.event.user:
key_value["event_user_email"] = notification.event.user.get("email", None)
key_value["event_user_username"] = notification.event.user.get("username", None)
context["key_value"]["event_user_email"] = notification.event.user.get("email", None)
context["key_value"]["event_user_username"] = notification.event.user.get(
"username", None
)
if notification.event:
subject += notification.event.action
context["title"] += notification.event.action
for key, value in notification.event.context.items():
if not isinstance(value, str):
continue
key_value[key] = value
context["key_value"][key] = value
else:
subject += notification.body[:75]
context["title"] += notification.body[:75]
# TODO: improve permission check
if notification.user.is_superuser:
context["source"] = {
"from": self.name,
}
mail = TemplateEmailMessage(
subject=subject,
subject=subject_prefix + context["title"],
to=[notification.user.email],
language=notification.user.locale(),
template_name="email/generic.html",
template_context={
"title": subject,
"body": notification.body,
"key_value": key_value,
},
template_name="email/event_notification.html",
template_context=context,
)
# Email is sent directly here, as the call to send() should have been from a task.
try:

View File

@ -1,205 +0,0 @@
/* authentik Email CSS */
* {
margin: 0;
font-family: Helvetica, Arial, sans-serif;
box-sizing: border-box;
font-size: 14px;
}
img {
max-width: 100%;
}
body {
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: none;
width: 100% !important;
height: 100%;
line-height: 1.6em;
}
table td {
vertical-align: top;
}
body {
background-color: #f6f6f6;
}
.body-wrap {
background-color: #f6f6f6;
width: 100%;
}
.container {
display: block !important;
max-width: 600px !important;
margin: 0 auto !important;
clear: both !important;
}
.content {
max-width: 600px;
margin: 0 auto;
display: block;
padding: 20px;
}
.main {
background-color: #fff;
border: 1px solid #e9e9e9;
}
.content-wrap {
padding: 20px;
}
.content-block {
padding: 0 0 20px;
}
.header {
width: 100%;
margin-bottom: 20px;
}
.footer {
width: 100%;
clear: both;
color: #999;
padding: 20px;
}
.footer p, .footer a, .footer td {
color: #999;
font-size: 12px;
}
h1, h2, h3 {
font-family: Helvetica, Arial, sans-serif;
color: #000;
margin: 40px 0 0;
line-height: 1.2em;
font-weight: 400;
}
h1 {
font-size: 32px;
font-weight: 500;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 14px;
font-weight: 600;
}
p, ul, ol {
margin-bottom: 10px;
font-weight: normal;
}
p li, ul li, ol li {
margin-left: 5px;
list-style-position: inside;
}
a {
color: #348eda;
text-decoration: underline;
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #348eda;
border: solid #348eda;
border-width: 10px 20px;
line-height: 2em;
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
text-transform: capitalize;
}
.btn-primary a {
color: #fff;
}
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.clear {
clear: both;
}
.alert {
font-size: 16px;
color: #fff;
font-weight: 500;
padding: 20px;
text-align: center;
}
.alert a {
color: #fff;
text-decoration: none;
font-weight: 500;
font-size: 16px;
}
.alert-brand {
background-color: #fd4b2d;
}
.alert-warning {
background-color: #F0AB00;
}
.alert-danger {
background-color: #C9190B;
}
.alert-success {
background-color: #3E8635;
}
.body {
margin: 40px auto;
text-align: left;
width: 80%;
}
.body td {
padding: 5px 0;
}
.body .body-items {
width: 100%;
}
.body .body-items td {
border-top: #eee 1px solid;
}
.body .body-items .total td {
border-top: 2px solid #333;
border-bottom: 2px solid #333;
font-weight: 700;
}
@media only screen and (max-width: 640px) {
body {
padding: 0 !important;
}
h1, h2, h3, h4 {
font-weight: 800 !important;
margin: 20px 0 5px !important;
}
h1 {
font-size: 22px !important;
}
h2 {
font-size: 18px !important;
}
h3 {
font-size: 16px !important;
}
.container {
padding: 0 !important;
width: 100% !important;
}
.content {
padding: 0 !important;
}
.content-wrap {
padding: 10px !important;
}
.body {
width: 100% !important;
}
}

View File

@ -4,35 +4,38 @@
{% load i18n %}
{% block content %}
<td>
<h2>
{% trans 'Welcome!' %}
</h2>
<p>
{% trans "We're excited to have you get started. First, you need to confirm your account. Just press the button below."%}
</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="center">
<h1>
{% trans 'Welcome!' %}
</h1>
</td>
</tr>
<tr>
<td align="center">
<table border="0">
<tr>
<td align="center">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td> <a id="confirm" href="{{ url }}" rel="noopener noreferrer" target="_blank">{% trans 'Confirm Account' %}</a> </td>
</tr>
</tbody>
</table>
<td align="center" style="max-width: 300px; padding: 20px 0; color: #212124;">
{% trans "We're excited to have you get started. First, you need to confirm your account. Just press the button below."%}
</td>
</tr>
</tbody>
</table>
<p>
<tr>
<td align="center" class="btn btn-primary">
<a id="confirm" href="{{ url }}" rel="noopener noreferrer" target="_blank">{% trans 'Confirm Account' %}</a>
</td>
</tr>
</table>
</td>
</tr>
<td>
{% endblock %}
{% block sub_content %}
<tr>
<td style="padding: 20px; font-size: 12px; color: #212124;word-break: break-all; overflow-wrap: break-word;" align="center">
{% blocktrans with url=url %}
If that doesn't work, copy and paste the following link in your browser: {{ url }}
{% endblocktrans %}
</p>
<p>
{% trans "If you have any questions, just reply to this email—we're always happy to help out." %}
</p>
</td>
</td>
</tr>
{% endblock %}

View File

@ -1,34 +1,131 @@
{% load authentik_stages_email %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
<style>{% inline_static_ascii "stages/email/css/base.css" %}</style>
</head>
<body itemscope itemtype="http://schema.org/EmailMessage">
<table class="body-wrap">
<html xmlns="http://www.w3.org/1999/xhtm=l">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width">
<style type="text/css">
body {
font-family: Arial, sans-serif;
font-size: 14px;
color: #212124;
}
h2 {
display: inline-block;
font-family: Arial, sans-serif;
font-size: 28px;
line-height: 125%;
font-weight: 700;
padding-top: 10px;
padding-bottom: 10px;
margin: 0;
}
.flexibleImage {
height: auto;
}
img.logo {
max-width: 100%;
max-height: 35px;
}
.properties-table {
width: 100%;
text-align: left;
font-size: 14px;
font-weight: 400;
font-family: Arial, sans-serif;
border-collapse: collapse;
}
.properties-table tr:first-child {
border-top: 1px solid rgba(196, 196, 196, 0.2);
}
.properties-table tr:first-child>td {
padding-top: 24px;
}
.properties-table tr:last-child {
border-bottom: 1px solid rgba(196, 196, 196, 0.2);
}
.properties-table tr:last-child>td {
padding-bottom: 24px;
}
.properties-table td {
line-height: 24px;
vertical-align: top;
padding: 4px 15px;
}
.td-right {
text-align: right;
white-space: nowrap;
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #348eda;
border: solid #348eda;
width: 100%;
line-height: 2em;
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
text-transform: capitalize;
}
.btn-primary a {
color: #fff;
}
</style>
</head>
<body>
<div class="wrapper">
<center>
<div style="-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; table-layout: fixed; width: 100%; max-width: 448px; padding: 60px 20px; font-size: 14px;">
<table border="0" align="center" width="100%">
<tr>
<td></td>
<td class="container" width="600">
<div class="content">
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
{% block content %}
{% endblock %}
</table>
<div class="footer">
<table width="100%">
<tr>
<td class="align-center content-block">Powered by <a href="https://goauthentik.io?utm_source=authentik&utm_medium=email">authentik</a>.</td>
</tr>
</table>
</div>
</div>
</td>
<td></td>
<td style="padding: 20px;border: 1px solid #c1c1c1;">
<table width="100%" style="background-color: #FFFFFF; border-spacing: 0; margin-top: 15px;">
<tr height="80">
<td align="center" style="padding: 20px 0;">
<img src="{% block logo_url %}cid:logo.png{% endblock %}" border="0=" alt="authentik logo" class="flexibleImage logo">
</td>
</tr>
{% block content %}
{% endblock %}
</table>
</td>
</tr>
</table>
</body>
<tr>
<td>
<table border="0" style="margin-top: 10px;" width="100%">
<tr>
<td style="background: #FAFBFB;">
<table style="width: 100%;">
{% block sub_content %}
{% endblock %}
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="center">
Powered by <a href="https://goauthentik.io?utm_source=authentik&utm_medium=email">authentik</a>.
</td>
</tr>
</table>
</div>
</center>
</div>
</body>
</html>

View File

@ -0,0 +1,52 @@
{% extends "email/base.html" %}
{% load i18n %}
{% block content %}
<tr>
<td align="center">
<h1>
{{ title }}
</h1>
</td>
</tr>
<tr>
<td align="center">
<table border="0">
<tr>
<td align="center" style="max-width: 300px; padding: 20px 0; color: #212124;">
{{ body }}
</td>
</tr>
{% if key_value %}
<tr>
<td>
<table class="properties-table" width="100%">
<tbody>
{% for key, value in key_value.items %}
<tr>
<td class="td-right">{{ key }}</td>
<td class="td-left">{{ value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</td>
</tr>
{% endif %}
</table>
</td>
</tr>
{% endblock %}
{% block sub_content %}
{% if source %}
<tr>
<td style="padding: 20px; font-size: 12px; color: #212124;" align="center">
{% blocktranslate with name=source.from %}
This email was sent from the notification transport <code>{{name}}</code>.
{% endblocktranslate %}
</td>
</tr>
{% endif %}
{% endblock %}

View File

@ -1,45 +0,0 @@
{% extends "email/base.html" %}
{% load i18n %}
{% block content %}
<tr>
<td class="alert alert-brand">
{{ title }}
</td>
</tr>
<tr>
<td class="content-wrap">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
{{ body }}
</td>
</tr>
{% if key_value %}
<tr>
<td class="content-block align-center">
<table class="body">
<tr>
<td>{% trans "Additional Information" %}</td>
</tr>
<tr>
<td>
<table class="body-items" cellpadding="0" cellspacing="0">
{% for key, value in key_value.items %}
<tr>
<td>{{ key }}</td>
<td class="align-right">{{ value }}</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
</table>
</td>
</tr>
{% endif %}
</table>
</td>
</tr>
{% endblock %}

View File

@ -5,49 +5,40 @@
{% block content %}
<tr>
<td class="alert alert-success">
{% blocktrans with username=user.username %}
Hi {{ username }},
{% endblocktrans %}
</td>
<td align="center">
<h1>
{% blocktrans with username=user.username %}
Hi {{ username }},
{% endblocktrans %}
</h1>
</td>
</tr>
<tr>
<td class="content-wrap">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
{% blocktrans %}
You recently requested to change your password for your authentik account. Use the button below to set a new password.
{% endblocktrans %}
</td>
</tr>
<tr>
<td class="content-block">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="center">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td> <a id="confirm" href="{{ url }}" rel="noopener noreferrer" target="_blank">{% trans 'Reset Password' %}</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td class="content-block">
{% blocktrans with expires=expires|naturaltime %}
If you did not request a password change, please ignore this Email. The link above is valid for {{ expires }}.
{% endblocktrans %}
</td>
</tr>
</table>
</td>
<td align="center">
<table border="0">
<tr>
<td align="center" style="max-width: 300px; padding: 20px 0; color: #212124;">
{% blocktrans %}
You recently requested to change your password for your authentik account. Use the button below to set a new password.
{% endblocktrans %}
</td>
</tr>
<tr>
<td align="center" class="btn btn-primary">
<a id="confirm" href="{{ url }}" rel="noopener noreferrer" target="_blank">{% trans 'Reset Password' %}</a>
</td>
</tr>
</table>
</td>
</tr>
{% endblock %}
{% block sub_content %}
<tr>
<td style="padding: 20px; font-size: 12px; color: #212124;" align="center">
{% blocktrans with expires=expires|naturaltime %}
If you did not request a password change, please ignore this Email. The link above is valid for {{ expires }}.
{% endblocktrans %}
</td>
</tr>
{% endblock %}

View File

@ -1,9 +1,21 @@
"""email utils"""
from email.mime.image import MIMEImage
from functools import lru_cache
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.utils import translation
@lru_cache()
def logo_data():
"""Get logo as MIME Image for emails"""
with open("web/icons/icon_left_brand.png", "rb") as _logo_file:
logo = MIMEImage(_logo_file.read())
logo.add_header("Content-ID", "logo.png")
return logo
class TemplateEmailMessage(EmailMultiAlternatives):
"""Wrapper around EmailMultiAlternatives with integrated template rendering"""
@ -12,4 +24,6 @@ class TemplateEmailMessage(EmailMultiAlternatives):
html_content = render_to_string(template_name, template_context)
super().__init__(**kwargs)
self.content_subtype = "html"
self.mixed_subtype = "related"
self.attach(logo_data())
self.attach_alternative(html_content, "text/html")

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-15 09:51+0000\n"
"POT-Creation-Date: 2023-10-02 12:46+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -375,63 +375,63 @@ msgstr ""
msgid "Event user"
msgstr ""
#: authentik/events/models.py:484
#: authentik/events/models.py:491
msgid "Notification Transport"
msgstr ""
#: authentik/events/models.py:485
#: authentik/events/models.py:492
msgid "Notification Transports"
msgstr ""
#: authentik/events/models.py:491
#: authentik/events/models.py:498
msgid "Notice"
msgstr ""
#: authentik/events/models.py:492
#: authentik/events/models.py:499
msgid "Warning"
msgstr ""
#: authentik/events/models.py:493
#: authentik/events/models.py:500
msgid "Alert"
msgstr ""
#: authentik/events/models.py:518
#: authentik/events/models.py:525
msgid "Notification"
msgstr ""
#: authentik/events/models.py:519
#: authentik/events/models.py:526
msgid "Notifications"
msgstr ""
#: authentik/events/models.py:529
#: authentik/events/models.py:536
msgid ""
"Select which transports should be used to notify the user. If none are "
"selected, the notification will only be shown in the authentik UI."
msgstr ""
#: authentik/events/models.py:537
#: authentik/events/models.py:544
msgid "Controls which severity level the created notifications will have."
msgstr ""
#: authentik/events/models.py:542
#: authentik/events/models.py:549
msgid ""
"Define which group of users this notification should be sent and shown to. "
"If left empty, Notification won't ben sent."
msgstr ""
#: authentik/events/models.py:560
#: authentik/events/models.py:567
msgid "Notification Rule"
msgstr ""
#: authentik/events/models.py:561
#: authentik/events/models.py:568
msgid "Notification Rules"
msgstr ""
#: authentik/events/models.py:581
#: authentik/events/models.py:588
msgid "Webhook Mapping"
msgstr ""
#: authentik/events/models.py:582
#: authentik/events/models.py:589
msgid "Webhook Mappings"
msgstr ""
@ -2099,21 +2099,21 @@ msgstr ""
msgid "Email sent."
msgstr ""
#: authentik/stages/email/templates/email/account_confirmation.html:9
#: authentik/stages/email/templates/email/account_confirmation.html:10
msgid "Welcome!"
msgstr ""
#: authentik/stages/email/templates/email/account_confirmation.html:12
#: authentik/stages/email/templates/email/account_confirmation.html:19
msgid ""
"We're excited to have you get started. First, you need to confirm your "
"account. Just press the button below."
msgstr ""
#: authentik/stages/email/templates/email/account_confirmation.html:21
#: authentik/stages/email/templates/email/account_confirmation.html:24
msgid "Confirm Account"
msgstr ""
#: authentik/stages/email/templates/email/account_confirmation.html:30
#: authentik/stages/email/templates/email/account_confirmation.html:36
#, python-format
msgid ""
"\n"
@ -2122,43 +2122,42 @@ msgid ""
" "
msgstr ""
#: authentik/stages/email/templates/email/account_confirmation.html:35
msgid ""
"If you have any questions, just reply to this email—we're always happy to "
"help out."
msgstr ""
#: authentik/stages/email/templates/email/generic.html:24
msgid "Additional Information"
msgstr ""
#: authentik/stages/email/templates/email/password_reset.html:9
#: authentik/stages/email/templates/email/event_notification.html:46
#, python-format
msgid ""
"\n"
" Hi %(username)s,\n"
" "
" This email was sent from the notification transport <code>%(name)s</"
"code>.\n"
" "
msgstr ""
#: authentik/stages/email/templates/email/password_reset.html:19
#: authentik/stages/email/templates/email/password_reset.html:10
#, python-format
msgid ""
"\n"
" You recently requested to change your password for your "
"authentik account. Use the button below to set a new password.\n"
" "
" Hi %(username)s,\n"
" "
msgstr ""
#: authentik/stages/email/templates/email/password_reset.html:33
#: authentik/stages/email/templates/email/password_reset.html:21
msgid ""
"\n"
" You recently requested to change your password for your authentik "
"account. Use the button below to set a new password.\n"
" "
msgstr ""
#: authentik/stages/email/templates/email/password_reset.html:28
msgid "Reset Password"
msgstr ""
#: authentik/stages/email/templates/email/password_reset.html:45
#: authentik/stages/email/templates/email/password_reset.html:39
#, python-format
msgid ""
"\n"
" If you did not request a password change, please ignore "
"this Email. The link above is valid for %(expires)s.\n"
" "
" If you did not request a password change, please ignore this Email. The "
"link above is valid for %(expires)s.\n"
" "
msgstr ""
#: authentik/stages/email/templates/email/setup.html:9

View File

@ -1,4 +1,4 @@
<?xml version="1.0" ?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<?xml version="1.0"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file target-language="fr" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body>
<trans-unit id="s4caed5b7a7e5d89b">
@ -613,9 +613,9 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="saa0e2675da69651b">
<source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source>
<target>L'URL &quot;
<x id="0" equiv-text="${this.url}"/>&quot; n'a pas été trouvée.</target>
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
<target>L'URL "
<x id="0" equiv-text="${this.url}"/>" n'a pas été trouvée.</target>
</trans-unit>
<trans-unit id="s58cd9c2fe836d9c6">
@ -1067,8 +1067,8 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="sa8384c9c26731f83">
<source>To allow any redirect URI, set this value to &quot;.*&quot;. Be aware of the possible security implications this can have.</source>
<target>Pour permettre n'importe quelle URI de redirection, définissez cette valeur sur &quot;.*&quot;. Soyez conscient des possibles implications de sécurité que cela peut avoir.</target>
<source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
<target>Pour permettre n'importe quelle URI de redirection, définissez cette valeur sur ".*". Soyez conscient des possibles implications de sécurité que cela peut avoir.</target>
</trans-unit>
<trans-unit id="s55787f4dfcdce52b">
@ -1298,7 +1298,7 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="s9c73dced379c37a2">
<source>Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you).</source>
<target>Utilisez ce fournisseur avec l'option &quot;auth_request&quot; de Nginx ou &quot;forwardAuth&quot; de Traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, &quot;/outpost.goauthentik.io&quot; doit être routé vers le poste avancé (lorsque vous utilisez un poste avancé géré, cela est fait pour vous).</target>
<target>Utilisez ce fournisseur avec l'option "auth_request" de Nginx ou "forwardAuth" de Traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, "/outpost.goauthentik.io" doit être routé vers le poste avancé (lorsque vous utilisez un poste avancé géré, cela est fait pour vous).</target>
</trans-unit>
<trans-unit id="s44c90273f08fb718">
@ -1645,7 +1645,7 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="s33ed903c210a6209">
<source>Token to authenticate with. Currently only bearer authentication is supported.</source>
<target>Jeton d'authentification à utiliser. Actuellement, seule l'authentification &quot;bearer authentication&quot; est prise en charge.</target>
<target>Jeton d'authentification à utiliser. Actuellement, seule l'authentification "bearer authentication" est prise en charge.</target>
</trans-unit>
<trans-unit id="sfc8bb104e2c05af8">
@ -1813,8 +1813,8 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="sa90b7809586c35ce">
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon &quot;fa-test&quot;.</source>
<target>Entrez une URL complète, un chemin relatif ou utilisez 'fa://fa-test' pour utiliser l'icône Font Awesome &quot;fa-test&quot;.</target>
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
<target>Entrez une URL complète, un chemin relatif ou utilisez 'fa://fa-test' pour utiliser l'icône Font Awesome "fa-test".</target>
</trans-unit>
<trans-unit id="s0410779cb47de312">
@ -3147,7 +3147,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s33683c3b1dbaf264">
<source>To use SSL instead, use 'ldaps://' and disable this option.</source>
<target>Pour utiliser SSL à la base, utilisez &quot;ldaps://&quot; et désactviez cette option.</target>
<target>Pour utiliser SSL à la base, utilisez "ldaps://" et désactviez cette option.</target>
</trans-unit>
<trans-unit id="s2221fef80f4753a2">
@ -3236,8 +3236,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s76768bebabb7d543">
<source>Field which contains members of a group. Note that if using the &quot;memberUid&quot; field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
<target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ &quot;memberUid&quot;, la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'</target>
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
<target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ "memberUid", la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'</target>
</trans-unit>
<trans-unit id="s026555347e589f0e">
@ -3532,7 +3532,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s3198c384c2f68b08">
<source>Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually.</source>
<target>Moment où les utilisateurs temporaires doivent être supprimés. Cela ne s'applique que si votre IDP utilise le format NameID &quot;transient&quot; et que l'utilisateur ne se déconnecte pas manuellement.</target>
<target>Moment où les utilisateurs temporaires doivent être supprimés. Cela ne s'applique que si votre IDP utilise le format NameID "transient" et que l'utilisateur ne se déconnecte pas manuellement.</target>
</trans-unit>
<trans-unit id="sb32e9c1faa0b8673">
@ -3700,7 +3700,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s9f8aac89fe318acc">
<source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source>
<target>Indiquer la valeur &quot;FriendlyName&quot; de l'attribut d'assertion (optionnel)</target>
<target>Indiquer la valeur "FriendlyName" de l'attribut d'assertion (optionnel)</target>
</trans-unit>
<trans-unit id="s851c108679653d2a">
@ -4029,8 +4029,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s7b1fba26d245cb1c">
<source>When using an external logging solution for archiving, this can be set to &quot;minutes=5&quot;.</source>
<target>En cas d'utilisation d'une solution de journalisation externe pour l'archivage, cette valeur peut être fixée à &quot;minutes=5&quot;.</target>
<source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
<target>En cas d'utilisation d'une solution de journalisation externe pour l'archivage, cette valeur peut être fixée à "minutes=5".</target>
</trans-unit>
<trans-unit id="s44536d20bb5c8257">
@ -4039,8 +4039,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s3bb51cabb02b997e">
<source>Format: &quot;weeks=3;days=2;hours=3,seconds=2&quot;.</source>
<target>Format : &quot;weeks=3;days=2;hours=3,seconds=2&quot;.</target>
<source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
<target>Format : "weeks=3;days=2;hours=3,seconds=2".</target>
</trans-unit>
<trans-unit id="s04bfd02201db5ab8">
@ -4236,10 +4236,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="sa95a538bfbb86111">
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> &quot;<x id="1" equiv-text="${this.obj?.name}"/>&quot;?</source>
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
<target>Êtes-vous sûr de vouloir mettre à jour
<x id="0" equiv-text="${this.objectLabel}"/>&quot;
<x id="1" equiv-text="${this.obj?.name}"/>&quot; ?</target>
<x id="0" equiv-text="${this.objectLabel}"/>"
<x id="1" equiv-text="${this.obj?.name}"/>" ?</target>
</trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6">
@ -5340,8 +5340,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="sdf1d8edef27236f0">
<source>A &quot;roaming&quot; authenticator, like a YubiKey</source>
<target>Un authentificateur &quot;itinérant&quot;, comme une YubiKey</target>
<source>A "roaming" authenticator, like a YubiKey</source>
<target>Un authentificateur "itinérant", comme une YubiKey</target>
</trans-unit>
<trans-unit id="sfffba7b23d8fb40c">
@ -5666,7 +5666,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s5170f9ef331949c0">
<source>Show arbitrary input fields to the user, for example during enrollment. Data is saved in the flow context under the 'prompt_data' variable.</source>
<target>Afficher des champs de saisie arbitraires à l'utilisateur, par exemple pendant l'inscription. Les données sont enregistrées dans le contexte du flux sous la variable &quot;prompt_data&quot;.</target>
<target>Afficher des champs de saisie arbitraires à l'utilisateur, par exemple pendant l'inscription. Les données sont enregistrées dans le contexte du flux sous la variable "prompt_data".</target>
</trans-unit>
<trans-unit id="s36cb242ac90353bc">
@ -5675,10 +5675,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s2d5f69929bb7221d">
<source><x id="0" equiv-text="${prompt.name}"/> (&quot;<x id="1" equiv-text="${prompt.fieldKey}"/>&quot;, of type <x id="2" equiv-text="${prompt.type}"/>)</source>
<source><x id="0" equiv-text="${prompt.name}"/> ("<x id="1" equiv-text="${prompt.fieldKey}"/>", of type <x id="2" equiv-text="${prompt.type}"/>)</source>
<target>
<x id="0" equiv-text="${prompt.name}"/>(&quot;
<x id="1" equiv-text="${prompt.fieldKey}"/>&quot;, de type
<x id="0" equiv-text="${prompt.name}"/>("
<x id="1" equiv-text="${prompt.fieldKey}"/>", de type
<x id="2" equiv-text="${prompt.type}"/>)</target>
</trans-unit>
@ -5727,8 +5727,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s1608b2f94fa0dbd4">
<source>If set to a duration above 0, the user will have the option to choose to &quot;stay signed in&quot;, which will extend their session by the time specified here.</source>
<target>Si défini à une durée supérieure à 0, l'utilisateur aura la possibilité de choisir de &quot;rester connecté&quot;, ce qui prolongera sa session jusqu'à la durée spécifiée ici.</target>
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
<target>Si défini à une durée supérieure à 0, l'utilisateur aura la possibilité de choisir de "rester connecté", ce qui prolongera sa session jusqu'à la durée spécifiée ici.</target>
</trans-unit>
<trans-unit id="s542a71bb8f41e057">
@ -6512,7 +6512,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="sa7fcf026bd25f231">
<source>Can be in the format of 'unix://' when connecting to a local docker daemon, using 'ssh://' to connect via SSH, or 'https://:2376' when connecting to a remote system.</source>
<target>Peut être au format &quot;unix://&quot; pour une connexion à un service docker local, &quot;ssh://&quot; pour une connexion via SSH, ou &quot;https://:2376&quot; pour une connexion à un système distant.</target>
<target>Peut être au format "unix://" pour une connexion à un service docker local, "ssh://" pour une connexion via SSH, ou "https://:2376" pour une connexion à un système distant.</target>
</trans-unit>
<trans-unit id="saf1d289e3137c2ea">
@ -7819,4 +7819,4 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" ?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<?xml version="1.0"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file target-language="zh-Hans" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body>
<trans-unit id="s4caed5b7a7e5d89b">
@ -613,9 +613,9 @@
</trans-unit>
<trans-unit id="saa0e2675da69651b">
<source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source>
<target>未找到 URL &quot;
<x id="0" equiv-text="${this.url}"/>&quot;。</target>
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
<target>未找到 URL "
<x id="0" equiv-text="${this.url}"/>"。</target>
</trans-unit>
<trans-unit id="s58cd9c2fe836d9c6">
@ -1067,8 +1067,8 @@
</trans-unit>
<trans-unit id="sa8384c9c26731f83">
<source>To allow any redirect URI, set this value to &quot;.*&quot;. Be aware of the possible security implications this can have.</source>
<target>要允许任何重定向 URI请将此值设置为 &quot;.*&quot;。请注意这可能带来的安全影响。</target>
<source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
<target>要允许任何重定向 URI请将此值设置为 ".*"。请注意这可能带来的安全影响。</target>
</trans-unit>
<trans-unit id="s55787f4dfcdce52b">
@ -1814,8 +1814,8 @@
</trans-unit>
<trans-unit id="sa90b7809586c35ce">
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon &quot;fa-test&quot;.</source>
<target>输入完整 URL、相对路径或者使用 'fa://fa-test' 来使用 Font Awesome 图标 &quot;fa-test&quot;。</target>
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
<target>输入完整 URL、相对路径或者使用 'fa://fa-test' 来使用 Font Awesome 图标 "fa-test"。</target>
</trans-unit>
<trans-unit id="s0410779cb47de312">
@ -3238,8 +3238,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s76768bebabb7d543">
<source>Field which contains members of a group. Note that if using the &quot;memberUid&quot; field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
<target>包含组成员的字段。请注意,如果使用 &quot;memberUid&quot; 字段,则假定该值包含相对可分辨名称。例如,'memberUid=some-user' 而不是 'memberUid=cn=some-user,ou=groups,...'</target>
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
<target>包含组成员的字段。请注意,如果使用 "memberUid" 字段,则假定该值包含相对可分辨名称。例如,'memberUid=some-user' 而不是 'memberUid=cn=some-user,ou=groups,...'</target>
</trans-unit>
<trans-unit id="s026555347e589f0e">
@ -4031,8 +4031,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s7b1fba26d245cb1c">
<source>When using an external logging solution for archiving, this can be set to &quot;minutes=5&quot;.</source>
<target>使用外部日志记录解决方案进行存档时,可以将其设置为 &quot;minutes=5&quot;。</target>
<source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
<target>使用外部日志记录解决方案进行存档时,可以将其设置为 "minutes=5"。</target>
</trans-unit>
<trans-unit id="s44536d20bb5c8257">
@ -4041,8 +4041,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s3bb51cabb02b997e">
<source>Format: &quot;weeks=3;days=2;hours=3,seconds=2&quot;.</source>
<target>格式:&quot;weeks=3;days=2;hours=3,seconds=2&quot;。</target>
<source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
<target>格式:"weeks=3;days=2;hours=3,seconds=2"。</target>
</trans-unit>
<trans-unit id="s04bfd02201db5ab8">
@ -4238,10 +4238,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="sa95a538bfbb86111">
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> &quot;<x id="1" equiv-text="${this.obj?.name}"/>&quot;?</source>
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
<target>您确定要更新
<x id="0" equiv-text="${this.objectLabel}"/>&quot;
<x id="1" equiv-text="${this.obj?.name}"/>&quot; 吗?</target>
<x id="0" equiv-text="${this.objectLabel}"/>"
<x id="1" equiv-text="${this.obj?.name}"/>" 吗?</target>
</trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6">
@ -5342,7 +5342,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="sdf1d8edef27236f0">
<source>A &quot;roaming&quot; authenticator, like a YubiKey</source>
<source>A "roaming" authenticator, like a YubiKey</source>
<target>像 YubiKey 这样的“漫游”身份验证器</target>
</trans-unit>
@ -5677,10 +5677,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s2d5f69929bb7221d">
<source><x id="0" equiv-text="${prompt.name}"/> (&quot;<x id="1" equiv-text="${prompt.fieldKey}"/>&quot;, of type <x id="2" equiv-text="${prompt.type}"/>)</source>
<source><x id="0" equiv-text="${prompt.name}"/> ("<x id="1" equiv-text="${prompt.fieldKey}"/>", of type <x id="2" equiv-text="${prompt.type}"/>)</source>
<target>
<x id="0" equiv-text="${prompt.name}"/>&quot;
<x id="1" equiv-text="${prompt.fieldKey}"/>&quot;,类型为
<x id="0" equiv-text="${prompt.name}"/>"
<x id="1" equiv-text="${prompt.fieldKey}"/>",类型为
<x id="2" equiv-text="${prompt.type}"/></target>
</trans-unit>
@ -5729,7 +5729,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s1608b2f94fa0dbd4">
<source>If set to a duration above 0, the user will have the option to choose to &quot;stay signed in&quot;, which will extend their session by the time specified here.</source>
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
<target>如果设置时长大于 0用户可以选择“保持登录”选项这将使用户的会话延长此处设置的时间。</target>
</trans-unit>
@ -7821,4 +7821,4 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
</body>
</file>
</xliff>
</xliff>