enterprise/providers/rac: add alert that enterprise is required for RAC (#8057)

add alert that enterprise is required for RAC

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2024-01-04 16:18:12 +01:00 committed by GitHub
parent b93ad8615c
commit 116ac30c72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 211 additions and 84 deletions

View File

@ -19,6 +19,7 @@ from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import MetaNameSerializer, PassiveSerializer, TypeCreateSerializer from authentik.core.api.utils import MetaNameSerializer, PassiveSerializer, TypeCreateSerializer
from authentik.core.expression.evaluator import PropertyMappingEvaluator from authentik.core.expression.evaluator import PropertyMappingEvaluator
from authentik.core.models import PropertyMapping from authentik.core.models import PropertyMapping
from authentik.enterprise.apps import EnterpriseConfig
from authentik.events.utils import sanitize_item from authentik.events.utils import sanitize_item
from authentik.lib.utils.reflection import all_subclasses from authentik.lib.utils.reflection import all_subclasses
from authentik.policies.api.exec import PolicyTestSerializer from authentik.policies.api.exec import PolicyTestSerializer
@ -95,6 +96,7 @@ class PropertyMappingViewSet(
"description": subclass.__doc__, "description": subclass.__doc__,
"component": subclass().component, "component": subclass().component,
"model_name": subclass._meta.model_name, "model_name": subclass._meta.model_name,
"requires_enterprise": isinstance(subclass._meta.app_config, EnterpriseConfig),
} }
) )
return Response(TypeCreateSerializer(data, many=True).data) return Response(TypeCreateSerializer(data, many=True).data)

View File

@ -16,6 +16,7 @@ from rest_framework.viewsets import GenericViewSet
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer
from authentik.core.models import Provider from authentik.core.models import Provider
from authentik.enterprise.apps import EnterpriseConfig
from authentik.lib.utils.reflection import all_subclasses from authentik.lib.utils.reflection import all_subclasses
@ -113,6 +114,7 @@ class ProviderViewSet(
"description": subclass.__doc__, "description": subclass.__doc__,
"component": subclass().component, "component": subclass().component,
"model_name": subclass._meta.model_name, "model_name": subclass._meta.model_name,
"requires_enterprise": isinstance(subclass._meta.app_config, EnterpriseConfig),
} }
) )
data.append( data.append(

View File

@ -5,7 +5,7 @@ from django.db.models import Model
from drf_spectacular.extensions import OpenApiSerializerFieldExtension from drf_spectacular.extensions import OpenApiSerializerFieldExtension
from drf_spectacular.plumbing import build_basic_type from drf_spectacular.plumbing import build_basic_type
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from rest_framework.fields import CharField, IntegerField, JSONField from rest_framework.fields import BooleanField, CharField, IntegerField, JSONField
from rest_framework.serializers import Serializer, SerializerMethodField, ValidationError from rest_framework.serializers import Serializer, SerializerMethodField, ValidationError
@ -74,6 +74,7 @@ class TypeCreateSerializer(PassiveSerializer):
description = CharField(required=True) description = CharField(required=True)
component = CharField(required=True) component = CharField(required=True)
model_name = CharField(required=True) model_name = CharField(required=True)
requires_enterprise = BooleanField(default=False)
class CacheSerializer(PassiveSerializer): class CacheSerializer(PassiveSerializer):

View File

@ -2,9 +2,11 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.utils.timezone import now from django.utils.timezone import now
from django.utils.translation import gettext as _
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema, inline_serializer from drf_spectacular.utils import extend_schema, inline_serializer
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import BooleanField, CharField, DateTimeField, IntegerField from rest_framework.fields import BooleanField, CharField, DateTimeField, IntegerField
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request from rest_framework.request import Request
@ -20,6 +22,18 @@ from authentik.enterprise.models import License, LicenseKey
from authentik.root.install_id import get_install_id from authentik.root.install_id import get_install_id
class EnterpriseRequiredMixin:
"""Mixin to validate that a valid enterprise license
exists before allowing to safe the object"""
def validate(self, attrs: dict) -> dict:
"""Check that a valid license exists"""
total = LicenseKey.get_total()
if not total.is_valid():
raise ValidationError(_("Enterprise is required to create/update this object."))
return super().validate(attrs)
class LicenseSerializer(ModelSerializer): class LicenseSerializer(ModelSerializer):
"""License Serializer""" """License Serializer"""

View File

@ -2,7 +2,11 @@
from authentik.blueprints.apps import ManagedAppConfig from authentik.blueprints.apps import ManagedAppConfig
class AuthentikEnterpriseConfig(ManagedAppConfig): class EnterpriseConfig(ManagedAppConfig):
"""Base app config for all enterprise apps"""
class AuthentikEnterpriseConfig(EnterpriseConfig):
"""Enterprise app config""" """Enterprise app config"""
name = "authentik.enterprise" name = "authentik.enterprise"

View File

@ -15,6 +15,7 @@ from structlog.stdlib import get_logger
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.core.models import Provider from authentik.core.models import Provider
from authentik.enterprise.api import EnterpriseRequiredMixin
from authentik.enterprise.providers.rac.api.providers import RACProviderSerializer from authentik.enterprise.providers.rac.api.providers import RACProviderSerializer
from authentik.enterprise.providers.rac.models import Endpoint from authentik.enterprise.providers.rac.models import Endpoint
from authentik.policies.engine import PolicyEngine from authentik.policies.engine import PolicyEngine
@ -28,7 +29,7 @@ def user_endpoint_cache_key(user_pk: str) -> str:
return f"goauthentik.io/providers/rac/endpoint_access/{user_pk}" return f"goauthentik.io/providers/rac/endpoint_access/{user_pk}"
class EndpointSerializer(ModelSerializer): class EndpointSerializer(EnterpriseRequiredMixin, ModelSerializer):
"""Endpoint Serializer""" """Endpoint Serializer"""
provider_obj = RACProviderSerializer(source="provider", read_only=True) provider_obj = RACProviderSerializer(source="provider", read_only=True)

View File

@ -5,10 +5,11 @@ from rest_framework.viewsets import ModelViewSet
from authentik.core.api.propertymappings import PropertyMappingSerializer from authentik.core.api.propertymappings import PropertyMappingSerializer
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import JSONDictField from authentik.core.api.utils import JSONDictField
from authentik.enterprise.api import EnterpriseRequiredMixin
from authentik.enterprise.providers.rac.models import RACPropertyMapping from authentik.enterprise.providers.rac.models import RACPropertyMapping
class RACPropertyMappingSerializer(PropertyMappingSerializer): class RACPropertyMappingSerializer(EnterpriseRequiredMixin, PropertyMappingSerializer):
"""RACPropertyMapping Serializer""" """RACPropertyMapping Serializer"""
static_settings = JSONDictField() static_settings = JSONDictField()

View File

@ -4,10 +4,11 @@ from rest_framework.viewsets import ModelViewSet
from authentik.core.api.providers import ProviderSerializer from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.enterprise.api import EnterpriseRequiredMixin
from authentik.enterprise.providers.rac.models import RACProvider from authentik.enterprise.providers.rac.models import RACProvider
class RACProviderSerializer(ProviderSerializer): class RACProviderSerializer(EnterpriseRequiredMixin, ProviderSerializer):
"""RACProvider Serializer""" """RACProvider Serializer"""
outpost_set = ListField(child=CharField(), read_only=True, source="outpost_set.all") outpost_set = ListField(child=CharField(), read_only=True, source="outpost_set.all")

View File

@ -1,8 +1,8 @@
"""RAC app config""" """RAC app config"""
from authentik.blueprints.apps import ManagedAppConfig from authentik.enterprise.apps import EnterpriseConfig
class AuthentikEnterpriseProviderRAC(ManagedAppConfig): class AuthentikEnterpriseProviderRAC(EnterpriseConfig):
"""authentik enterprise rac app config""" """authentik enterprise rac app config"""
name = "authentik.enterprise.providers.rac" name = "authentik.enterprise.providers.rac"

View File

@ -35,7 +35,7 @@ class AuthenticationMode(models.TextChoices):
class RACProvider(Provider): class RACProvider(Provider):
"""Remotely access computers/servers""" """Remotely access computers/servers via RDP/SSH/VNC."""
settings = models.JSONField(default=dict) settings = models.JSONField(default=dict)
auth_mode = models.TextField( auth_mode = models.TextField(

View File

@ -19158,6 +19158,7 @@ paths:
- tr - tr
- tt - tt
- udm - udm
- ug
- uk - uk
- ur - ur
- uz - uz
@ -42957,6 +42958,9 @@ components:
type: string type: string
model_name: model_name:
type: string type: string
requires_enterprise:
type: boolean
default: false
required: required:
- component - component
- description - description

View File

@ -13,21 +13,24 @@ import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { msg, str } from "@lit/localize"; import { msg, str } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html, nothing } from "lit";
import { property } from "lit/decorators.js"; import { property, state } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFForm from "@patternfly/patternfly/components/Form/form.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css";
import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { PropertymappingsApi, TypeCreate } from "@goauthentik/api"; import { EnterpriseApi, LicenseSummary, PropertymappingsApi, TypeCreate } from "@goauthentik/api";
@customElement("ak-property-mapping-wizard-initial") @customElement("ak-property-mapping-wizard-initial")
export class InitialPropertyMappingWizardPage extends WizardPage { export class InitialPropertyMappingWizardPage extends WizardPage {
@property({ attribute: false }) @property({ attribute: false })
mappingTypes: TypeCreate[] = []; mappingTypes: TypeCreate[] = [];
@property({ attribute: false })
enterprise?: LicenseSummary;
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFForm, PFButton, PFRadio]; return [PFBase, PFForm, PFButton, PFRadio];
} }
@ -60,11 +63,20 @@ export class InitialPropertyMappingWizardPage extends WizardPage {
]; ];
this.host.isValid = true; this.host.isValid = true;
}} }}
?disabled=${type.requiresEnterprise ? !this.enterprise?.hasLicense : false}
/> />
<label class="pf-c-radio__label" for=${`${type.component}-${type.modelName}`} <label class="pf-c-radio__label" for=${`${type.component}-${type.modelName}`}
>${type.name}</label >${type.name}</label
> >
<span class="pf-c-radio__description">${type.description}</span> <span class="pf-c-radio__description">${type.description}</span>
${type.requiresEnterprise && !this.enterprise?.hasLicense
? html`
<ak-alert class="pf-c-radio__description" ?inline=${true}>
${msg("Provider require enterprise.")}
<a href="#/enterprise/licenses">${msg("Learn more")}</a>
</ak-alert>
`
: nothing}
</div>`; </div>`;
})} })}
</form>`; </form>`;
@ -80,10 +92,16 @@ export class PropertyMappingWizard extends AKElement {
@property({ attribute: false }) @property({ attribute: false })
mappingTypes: TypeCreate[] = []; mappingTypes: TypeCreate[] = [];
firstUpdated(): void { @state()
new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllTypesList().then((types) => { enterprise?: LicenseSummary;
this.mappingTypes = types;
}); async firstUpdated(): Promise<void> {
this.mappingTypes = await new PropertymappingsApi(
DEFAULT_CONFIG,
).propertymappingsAllTypesList();
this.enterprise = await new EnterpriseApi(
DEFAULT_CONFIG,
).enterpriseLicenseSummaryRetrieve();
} }
render(): TemplateResult { render(): TemplateResult {

View File

@ -4,6 +4,7 @@ import "@goauthentik/admin/providers/proxy/ProxyProviderForm";
import "@goauthentik/admin/providers/saml/SAMLProviderForm"; import "@goauthentik/admin/providers/saml/SAMLProviderForm";
import "@goauthentik/admin/providers/saml/SAMLProviderImportForm"; import "@goauthentik/admin/providers/saml/SAMLProviderImportForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/elements/Alert";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/forms/ProxyForm"; import "@goauthentik/elements/forms/ProxyForm";
import { paramURL } from "@goauthentik/elements/router/RouterOutlet"; import { paramURL } from "@goauthentik/elements/router/RouterOutlet";
@ -13,8 +14,8 @@ import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
import { msg, str } from "@lit/localize"; import { msg, str } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { CSSResult, TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html, nothing } from "lit";
import { property } from "lit/decorators.js"; import { property, state } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFForm from "@patternfly/patternfly/components/Form/form.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css";
@ -22,13 +23,16 @@ import PFHint from "@patternfly/patternfly/components/Hint/hint.css";
import PFRadio from "@patternfly/patternfly/components/Radio/radio.css"; import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { ProvidersApi, TypeCreate } from "@goauthentik/api"; import { EnterpriseApi, LicenseSummary, ProvidersApi, TypeCreate } from "@goauthentik/api";
@customElement("ak-provider-wizard-initial") @customElement("ak-provider-wizard-initial")
export class InitialProviderWizardPage extends WizardPage { export class InitialProviderWizardPage extends WizardPage {
@property({ attribute: false }) @property({ attribute: false })
providerTypes: TypeCreate[] = []; providerTypes: TypeCreate[] = [];
@property({ attribute: false })
enterprise?: LicenseSummary;
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFForm, PFHint, PFButton, PFRadio]; return [PFBase, PFForm, PFHint, PFButton, PFRadio];
} }
@ -79,9 +83,18 @@ export class InitialProviderWizardPage extends WizardPage {
this.host.steps = ["initial", `type-${type.component}`]; this.host.steps = ["initial", `type-${type.component}`];
this.host.isValid = true; this.host.isValid = true;
}} }}
?disabled=${type.requiresEnterprise ? !this.enterprise?.hasLicense : false}
/> />
<label class="pf-c-radio__label" for=${type.component}>${type.name}</label> <label class="pf-c-radio__label" for=${type.component}>${type.name}</label>
<span class="pf-c-radio__description">${type.description}</span> <span class="pf-c-radio__description">${type.description}</span>
${type.requiresEnterprise && !this.enterprise?.hasLicense
? html`
<ak-alert class="pf-c-radio__description" ?inline=${true}>
${msg("Provider require enterprise.")}
<a href="#/enterprise/licenses">${msg("Learn more")}</a>
</ak-alert>
`
: nothing}
</div>`; </div>`;
})} })}
</form>`; </form>`;
@ -100,15 +113,19 @@ export class ProviderWizard extends AKElement {
@property({ attribute: false }) @property({ attribute: false })
providerTypes: TypeCreate[] = []; providerTypes: TypeCreate[] = [];
@state()
enterprise?: LicenseSummary;
@property({ attribute: false }) @property({ attribute: false })
finalHandler: () => Promise<void> = () => { finalHandler: () => Promise<void> = () => {
return Promise.resolve(); return Promise.resolve();
}; };
firstUpdated(): void { async firstUpdated(): Promise<void> {
new ProvidersApi(DEFAULT_CONFIG).providersAllTypesList().then((types) => { this.providerTypes = await new ProvidersApi(DEFAULT_CONFIG).providersAllTypesList();
this.providerTypes = types; this.enterprise = await new EnterpriseApi(
}); DEFAULT_CONFIG,
).enterpriseLicenseSummaryRetrieve();
} }
render(): TemplateResult { render(): TemplateResult {
@ -121,7 +138,11 @@ export class ProviderWizard extends AKElement {
return this.finalHandler(); return this.finalHandler();
}} }}
> >
<ak-provider-wizard-initial slot="initial" .providerTypes=${this.providerTypes}> <ak-provider-wizard-initial
slot="initial"
.providerTypes=${this.providerTypes}
.enterprise=${this.enterprise}
>
</ak-provider-wizard-initial> </ak-provider-wizard-initial>
${this.providerTypes.map((type) => { ${this.providerTypes.map((type) => {
return html` return html`

View File

@ -21,10 +21,8 @@ export class EnterpriseStatusBanner extends AKElement {
return [PFBanner]; return [PFBanner];
} }
firstUpdated(): void { async firstUpdated(): Promise<void> {
new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseSummaryRetrieve().then((b) => { this.summary = await new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseSummaryRetrieve();
this.summary = b;
});
} }
renderBanner(): TemplateResult { renderBanner(): TemplateResult {

View File

@ -6237,6 +6237,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -6513,6 +6513,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -6153,6 +6153,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

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"> <file target-language="fr" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body> <body>
<trans-unit id="s4caed5b7a7e5d89b"> <trans-unit id="s4caed5b7a7e5d89b">
@ -613,9 +613,9 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit> </trans-unit>
<trans-unit id="saa0e2675da69651b"> <trans-unit id="saa0e2675da69651b">
<source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source> <source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
<target>L'URL &quot; <target>L'URL "
<x id="0" equiv-text="${this.url}"/>&quot; n'a pas été trouvée.</target> <x id="0" equiv-text="${this.url}"/>" n'a pas été trouvée.</target>
</trans-unit> </trans-unit>
<trans-unit id="s58cd9c2fe836d9c6"> <trans-unit id="s58cd9c2fe836d9c6">
@ -1057,8 +1057,8 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit> </trans-unit>
<trans-unit id="sa8384c9c26731f83"> <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> <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 &quot;.*&quot;. Soyez conscient des possibles implications de sécurité que cela peut avoir.</target> <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>
<trans-unit id="s55787f4dfcdce52b"> <trans-unit id="s55787f4dfcdce52b">
@ -1630,7 +1630,7 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit> </trans-unit>
<trans-unit id="s33ed903c210a6209"> <trans-unit id="s33ed903c210a6209">
<source>Token to authenticate with. Currently only bearer authentication is supported.</source> <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>
<trans-unit id="sfc8bb104e2c05af8"> <trans-unit id="sfc8bb104e2c05af8">
@ -1798,8 +1798,8 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit> </trans-unit>
<trans-unit id="sa90b7809586c35ce"> <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> <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 &quot;fa-test&quot;.</target> <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>
<trans-unit id="s0410779cb47de312"> <trans-unit id="s0410779cb47de312">
@ -2892,7 +2892,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s33683c3b1dbaf264"> <trans-unit id="s33683c3b1dbaf264">
<source>To use SSL instead, use 'ldaps://' and disable this option.</source> <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>
<trans-unit id="s2221fef80f4753a2"> <trans-unit id="s2221fef80f4753a2">
@ -2981,8 +2981,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s76768bebabb7d543"> <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> <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 &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> <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>
<trans-unit id="s026555347e589f0e"> <trans-unit id="s026555347e589f0e">
@ -3277,7 +3277,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s3198c384c2f68b08"> <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> <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>
<trans-unit id="sb32e9c1faa0b8673"> <trans-unit id="sb32e9c1faa0b8673">
@ -3445,7 +3445,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s9f8aac89fe318acc"> <trans-unit id="s9f8aac89fe318acc">
<source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source> <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>
<trans-unit id="s851c108679653d2a"> <trans-unit id="s851c108679653d2a">
@ -3774,8 +3774,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s7b1fba26d245cb1c"> <trans-unit id="s7b1fba26d245cb1c">
<source>When using an external logging solution for archiving, this can be set to &quot;minutes=5&quot;.</source> <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 à &quot;minutes=5&quot;.</target> <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>
<trans-unit id="s44536d20bb5c8257"> <trans-unit id="s44536d20bb5c8257">
@ -3784,8 +3784,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s3bb51cabb02b997e"> <trans-unit id="s3bb51cabb02b997e">
<source>Format: &quot;weeks=3;days=2;hours=3,seconds=2&quot;.</source> <source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
<target>Format : &quot;weeks=3;days=2;hours=3,seconds=2&quot;.</target> <target>Format : "weeks=3;days=2;hours=3,seconds=2".</target>
</trans-unit> </trans-unit>
<trans-unit id="s04bfd02201db5ab8"> <trans-unit id="s04bfd02201db5ab8">
@ -3981,10 +3981,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="sa95a538bfbb86111"> <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 <target>Êtes-vous sûr de vouloir mettre à jour
<x id="0" equiv-text="${this.objectLabel}"/>&quot; <x id="0" equiv-text="${this.objectLabel}"/>"
<x id="1" equiv-text="${this.obj?.name}"/>&quot; ?</target> <x id="1" equiv-text="${this.obj?.name}"/>" ?</target>
</trans-unit> </trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6"> <trans-unit id="sc92d7cfb6ee1fec6">
@ -5070,8 +5070,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="sdf1d8edef27236f0"> <trans-unit id="sdf1d8edef27236f0">
<source>A &quot;roaming&quot; authenticator, like a YubiKey</source> <source>A "roaming" authenticator, like a YubiKey</source>
<target>Un authentificateur &quot;itinérant&quot;, comme une YubiKey</target> <target>Un authentificateur "itinérant", comme une YubiKey</target>
</trans-unit> </trans-unit>
<trans-unit id="sfffba7b23d8fb40c"> <trans-unit id="sfffba7b23d8fb40c">
@ -5396,7 +5396,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s5170f9ef331949c0"> <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> <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>
<trans-unit id="s36cb242ac90353bc"> <trans-unit id="s36cb242ac90353bc">
@ -5405,10 +5405,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s2d5f69929bb7221d"> <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> <target>
<x id="0" equiv-text="${prompt.name}"/>(&quot; <x id="0" equiv-text="${prompt.name}"/>("
<x id="1" equiv-text="${prompt.fieldKey}"/>&quot;, de type <x id="1" equiv-text="${prompt.fieldKey}"/>", de type
<x id="2" equiv-text="${prompt.type}"/>)</target> <x id="2" equiv-text="${prompt.type}"/>)</target>
</trans-unit> </trans-unit>
@ -5457,8 +5457,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s1608b2f94fa0dbd4"> <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>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> <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>
<trans-unit id="s542a71bb8f41e057"> <trans-unit id="s542a71bb8f41e057">
@ -6242,7 +6242,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit> </trans-unit>
<trans-unit id="sa7fcf026bd25f231"> <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> <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>
<trans-unit id="saf1d289e3137c2ea"> <trans-unit id="saf1d289e3137c2ea">
@ -7549,7 +7549,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit> </trans-unit>
<trans-unit id="sff0ac1ace2d90709"> <trans-unit id="sff0ac1ace2d90709">
<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 managed outpost, this is done for you).</source> <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 managed 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>
<trans-unit id="scb58b8a60cad8762"> <trans-unit id="scb58b8a60cad8762">
<source>Default relay state</source> <source>Default relay state</source>
@ -7963,7 +7963,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<target>Utilisateur créé et ajouté au groupe <x id="0" equiv-text="${this.group.name}"/> avec succès</target> <target>Utilisateur créé et ajouté au groupe <x id="0" equiv-text="${this.group.name}"/> avec succès</target>
</trans-unit> </trans-unit>
<trans-unit id="s824e0943a7104668"> <trans-unit id="s824e0943a7104668">
<source>This user will be added to the group &quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&quot;.</source> <source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source>
<target>Cet utilisateur sera ajouté au groupe &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;.</target> <target>Cet utilisateur sera ajouté au groupe &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s62e7f6ed7d9cb3ca"> <trans-unit id="s62e7f6ed7d9cb3ca">
@ -8201,6 +8201,12 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
<target>Détermine combien de temps une session dure avant déconnexion et ré-authorisation.</target> <target>Détermine combien de temps une session dure avant déconnexion et ré-authorisation.</target>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -6361,6 +6361,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -8099,4 +8099,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
</trans-unit> </trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit>
</body></file></xliff> </body></file></xliff>

View File

@ -6146,6 +6146,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

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"> <file target-language="zh-Hans" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body> <body>
<trans-unit id="s4caed5b7a7e5d89b"> <trans-unit id="s4caed5b7a7e5d89b">
@ -613,9 +613,9 @@
</trans-unit> </trans-unit>
<trans-unit id="saa0e2675da69651b"> <trans-unit id="saa0e2675da69651b">
<source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source> <source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
<target>未找到 URL &quot; <target>未找到 URL "
<x id="0" equiv-text="${this.url}"/>&quot;。</target> <x id="0" equiv-text="${this.url}"/>"。</target>
</trans-unit> </trans-unit>
<trans-unit id="s58cd9c2fe836d9c6"> <trans-unit id="s58cd9c2fe836d9c6">
@ -1057,8 +1057,8 @@
</trans-unit> </trans-unit>
<trans-unit id="sa8384c9c26731f83"> <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> <source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
<target>要允许任何重定向 URI请将此值设置为 &quot;.*&quot;。请注意这可能带来的安全影响。</target> <target>要允许任何重定向 URI请将此值设置为 ".*"。请注意这可能带来的安全影响。</target>
</trans-unit> </trans-unit>
<trans-unit id="s55787f4dfcdce52b"> <trans-unit id="s55787f4dfcdce52b">
@ -1799,8 +1799,8 @@
</trans-unit> </trans-unit>
<trans-unit id="sa90b7809586c35ce"> <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> <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 图标 &quot;fa-test&quot;。</target> <target>输入完整 URL、相对路径或者使用 'fa://fa-test' 来使用 Font Awesome 图标 "fa-test"。</target>
</trans-unit> </trans-unit>
<trans-unit id="s0410779cb47de312"> <trans-unit id="s0410779cb47de312">
@ -2983,8 +2983,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s76768bebabb7d543"> <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> <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>包含组成员的字段。请注意,如果使用 &quot;memberUid&quot; 字段,则假定该值包含相对可分辨名称。例如,'memberUid=some-user' 而不是 'memberUid=cn=some-user,ou=groups,...'</target> <target>包含组成员的字段。请注意,如果使用 "memberUid" 字段,则假定该值包含相对可分辨名称。例如,'memberUid=some-user' 而不是 'memberUid=cn=some-user,ou=groups,...'</target>
</trans-unit> </trans-unit>
<trans-unit id="s026555347e589f0e"> <trans-unit id="s026555347e589f0e">
@ -3776,8 +3776,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s7b1fba26d245cb1c"> <trans-unit id="s7b1fba26d245cb1c">
<source>When using an external logging solution for archiving, this can be set to &quot;minutes=5&quot;.</source> <source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
<target>使用外部日志记录解决方案进行存档时,可以将其设置为 &quot;minutes=5&quot;。</target> <target>使用外部日志记录解决方案进行存档时,可以将其设置为 "minutes=5"。</target>
</trans-unit> </trans-unit>
<trans-unit id="s44536d20bb5c8257"> <trans-unit id="s44536d20bb5c8257">
@ -3786,8 +3786,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s3bb51cabb02b997e"> <trans-unit id="s3bb51cabb02b997e">
<source>Format: &quot;weeks=3;days=2;hours=3,seconds=2&quot;.</source> <source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
<target>格式:&quot;weeks=3;days=2;hours=3,seconds=2&quot;。</target> <target>格式:"weeks=3;days=2;hours=3,seconds=2"。</target>
</trans-unit> </trans-unit>
<trans-unit id="s04bfd02201db5ab8"> <trans-unit id="s04bfd02201db5ab8">
@ -3983,10 +3983,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="sa95a538bfbb86111"> <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>您确定要更新 <target>您确定要更新
<x id="0" equiv-text="${this.objectLabel}"/>&quot; <x id="0" equiv-text="${this.objectLabel}"/>"
<x id="1" equiv-text="${this.obj?.name}"/>&quot; 吗?</target> <x id="1" equiv-text="${this.obj?.name}"/>" 吗?</target>
</trans-unit> </trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6"> <trans-unit id="sc92d7cfb6ee1fec6">
@ -5072,7 +5072,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="sdf1d8edef27236f0"> <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> <target>像 YubiKey 这样的“漫游”身份验证器</target>
</trans-unit> </trans-unit>
@ -5407,10 +5407,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s2d5f69929bb7221d"> <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> <target>
<x id="0" equiv-text="${prompt.name}"/>&quot; <x id="0" equiv-text="${prompt.name}"/>"
<x id="1" equiv-text="${prompt.fieldKey}"/>&quot;,类型为 <x id="1" equiv-text="${prompt.fieldKey}"/>",类型为
<x id="2" equiv-text="${prompt.type}"/></target> <x id="2" equiv-text="${prompt.type}"/></target>
</trans-unit> </trans-unit>
@ -5459,7 +5459,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s1608b2f94fa0dbd4"> <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> <target>如果设置时长大于 0用户可以选择“保持登录”选项这将使用户的会话延长此处设置的时间。</target>
</trans-unit> </trans-unit>
@ -7965,7 +7965,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>成功创建用户并添加到组 <x id="0" equiv-text="${this.group.name}"/></target> <target>成功创建用户并添加到组 <x id="0" equiv-text="${this.group.name}"/></target>
</trans-unit> </trans-unit>
<trans-unit id="s824e0943a7104668"> <trans-unit id="s824e0943a7104668">
<source>This user will be added to the group &quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&quot;.</source> <source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source>
<target>此用户将会被添加到组 &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;。</target> <target>此用户将会被添加到组 &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;。</target>
</trans-unit> </trans-unit>
<trans-unit id="s62e7f6ed7d9cb3ca"> <trans-unit id="s62e7f6ed7d9cb3ca">
@ -8203,6 +8203,12 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
<target>设置会话在被断开连接并需要重新授权之前持续的时间。</target> <target>设置会话在被断开连接并需要重新授权之前持续的时间。</target>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -6194,6 +6194,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -8083,6 +8083,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s6dd297c217729828"> <trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source> <source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
</trans-unit>
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>