mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 21:47:23 +00:00
feat: manage restrictions in console (#6965)
* feat: return 404 or 409 if org reg disallowed * fix: system limit permissions * feat: add iam limits api * feat: disallow public org registrations on default instance * add integration test * test: integration * fix test * docs: describe public org registrations * avoid updating docs deps * fix system limits integration test * silence integration tests * fix linting * ignore strange linter complaints * review * improve reset properties naming * redefine the api * use restrictions aggregate * test query * simplify and test projection * test commands * fix unit tests * move integration test * support restrictions on default instance * also test GetRestrictions * self review * lint * abstract away resource owner * fix tests * configure supported languages * fix allowed languages * fix tests * default lang must not be restricted * preferred language must be allowed * change preferred languages * check languages everywhere * lint * test command side * lint * add integration test * add integration test * restrict supported ui locales * lint * lint * cleanup * lint * allow undefined preferred language * fix integration tests * update main * fix env var * ignore linter * ignore linter * improve integration test config * reduce cognitive complexity * compile * fix(console): switch back to saved language * feat(API): get allowed languages * fix(console): only make allowed languages selectable * warn when editing not allowed languages * feat: manage restrictions in console * check for duplicates * remove useless restriction checks * review * revert restriction renaming * manage languages * fix language restrictions * lint * generate * allow custom texts for supported langs for now * fix tests * cleanup * cleanup * cleanup * lint * unsupported preferred lang is allowed * fix integration test * allow unsupported preferred languages * lint * fix languages lists * simplify default language selection * translate * discard * lint * load languages for tests * load languages * lint * cleanup * lint * cleanup * get allowed only on admin * cleanup * reduce flakiness on very limited postgres * simplify langSvc * refactor according to suggestions in pr * lint * improve ux * update central allowed languages * set first allowed language as default * readd lost translations * disable sorting disallowed languages * fix permissions * lint * selectionchange for language in msg texts * initialize login texts * init message texts * lint * fix drag and drop list styles * start from 1 * cleanup * prettier * correct orgdefaultlabel * unsubscribe * lint * docs: describe language settings --------- Co-authored-by: peintnermax <max@caos.ch>
This commit is contained in:
parent
3842319d07
commit
d639c5200a
@ -1,27 +0,0 @@
|
||||
<h2>{{ 'SETTING.DEFAULTLANGUAGE' | translate }}</h2>
|
||||
|
||||
<div class="spinner-wr">
|
||||
<mat-spinner diameter="30" *ngIf="loading" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<cnsl-form-field class="default-language" label="Default Language" required="true">
|
||||
<cnsl-label>{{ 'SETTING.DEFAULTLANGUAGE' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="defaultLanguage" [disabled]="(['iam.policy.write'] | hasRole | async) === false">
|
||||
<mat-option *ngFor="let lang of defaultLanguageOptions" [value]="lang">
|
||||
{{ lang }} - {{ 'SETTING.LANGUAGE.' + lang | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<div class="general-btn-container">
|
||||
<button
|
||||
class="save-button"
|
||||
(click)="savePolicy()"
|
||||
color="primary"
|
||||
type="submit"
|
||||
mat-raised-button
|
||||
[disabled]="(['iam.policy.write'] | hasRole | async) === false"
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
@ -1,18 +0,0 @@
|
||||
.spinner-wr {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.default-language {
|
||||
max-width: 400px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.general-btn-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 1rem;
|
||||
|
||||
.save-button {
|
||||
display: block;
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { SetDefaultLanguageResponse } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-general-settings',
|
||||
templateUrl: './general-settings.component.html',
|
||||
styleUrls: ['./general-settings.component.scss'],
|
||||
})
|
||||
export class GeneralSettingsComponent implements OnInit {
|
||||
public defaultLanguage: string = '';
|
||||
public defaultLanguageOptions: string[] = [];
|
||||
|
||||
public loading: boolean = false;
|
||||
constructor(
|
||||
private service: AdminService,
|
||||
private toast: ToastService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.fetchData();
|
||||
}
|
||||
|
||||
private fetchData(): void {
|
||||
this.service.getDefaultLanguage().then((langResp) => {
|
||||
this.defaultLanguage = langResp.language;
|
||||
});
|
||||
this.service.getAllowedLanguages().then((supportedResp) => {
|
||||
this.defaultLanguageOptions = supportedResp.languagesList;
|
||||
});
|
||||
}
|
||||
|
||||
private updateData(): Promise<SetDefaultLanguageResponse.AsObject> {
|
||||
return (this.service as AdminService).setDefaultLanguage(this.defaultLanguage);
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
const prom = this.updateData();
|
||||
this.loading = true;
|
||||
if (prom) {
|
||||
prom
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.LOGIN_POLICY.SAVED', true);
|
||||
this.loading = false;
|
||||
setTimeout(() => {
|
||||
this.fetchData();
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.loading = false;
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { CardModule } from '../../card/card.module';
|
||||
import { FormFieldModule } from '../../form-field/form-field.module';
|
||||
import { GeneralSettingsComponent } from './general-settings.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [GeneralSettingsComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
CardModule,
|
||||
FormsModule,
|
||||
MatButtonModule,
|
||||
FormFieldModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSelectModule,
|
||||
HasRolePipeModule,
|
||||
TranslateModule,
|
||||
],
|
||||
exports: [GeneralSettingsComponent],
|
||||
})
|
||||
export class GeneralSettingsModule {}
|
@ -0,0 +1,135 @@
|
||||
<h2>{{ 'SETTING.LANGUAGES.TITLE' | translate }}</h2>
|
||||
|
||||
<div class="spinner-wr">
|
||||
<mat-spinner diameter="30" *ngIf="loading" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<form class="languages-container-wrapper">
|
||||
<div class="languages-container">
|
||||
<div
|
||||
class="languages-list"
|
||||
cdkDropList
|
||||
id="allowed"
|
||||
[cdkDropListConnectedTo]="['notallowed']"
|
||||
(cdkDropListDropped)="drop($event)"
|
||||
[cdkDropListData]="(localState$ | async)!.allowed"
|
||||
>
|
||||
<div class="languages-top-row">
|
||||
<span class="label">{{ 'SETTING.LANGUAGES.ALLOWED' | translate }}</span>
|
||||
<button
|
||||
class="list-button"
|
||||
[disabled]="(canWriteRestrictions$ | async) === false"
|
||||
(click)="allowAll()"
|
||||
mat-stroked-button
|
||||
>
|
||||
<div class="cnsl-action-button">
|
||||
<i class="las la-object-group"></i><span>{{ 'SETTING.LANGUAGES.ALLOW_ALL' | translate }}</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="languages-drop-target">
|
||||
<div
|
||||
class="card languages-box"
|
||||
*ngFor="let lang of (localState$ | async)!.allowed; index as i"
|
||||
[cdkDragData]="lang"
|
||||
cdkDrag
|
||||
[cdkDragDisabled]="(canWriteRestrictions$ | async) === false"
|
||||
mat-list-item
|
||||
>
|
||||
<span class="index">{{ i + 1 }}</span>
|
||||
<span class="locale">{{ lang }}</span>
|
||||
<span class="lang">{{ 'SETTING.LANGUAGES.OPTIONS.' + lang | translate }} </span>
|
||||
<span *ngIf="lang === (defaultLang$ | async)" class="state orgdefaultlabel">{{
|
||||
'SETTING.LANGUAGES.DEFAULT' | translate
|
||||
}}</span>
|
||||
|
||||
<button
|
||||
(click)="$event.stopPropagation()"
|
||||
*ngIf="lang !== (defaultLang$ | async) && (isRemotelyAllowed$(lang) | async) === true"
|
||||
mat-icon-button
|
||||
class="more-button"
|
||||
[matMenuTriggerFor]="actions"
|
||||
data-e2e="table-actions-button"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
|
||||
<mat-menu #actions="matMenu" xPosition="before" class="language-actions-menu">
|
||||
<button
|
||||
menuActions
|
||||
mat-menu-item
|
||||
(click)="setDefaultLang(lang)"
|
||||
[disabled]="(canWriteDefaultLanguage$ | async) === false"
|
||||
>
|
||||
{{ 'SETTING.LANGUAGES.SETASDEFAULT' | translate }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="languages-container">
|
||||
<div
|
||||
class="languages-list"
|
||||
cdkDropList
|
||||
id="notallowed"
|
||||
[cdkDropListConnectedTo]="['allowed']"
|
||||
(cdkDropListDropped)="drop($event)"
|
||||
[cdkDropListData]="(localState$ | async)!.notAllowed"
|
||||
[cdkDropListEnterPredicate]="defaultLangPredicate"
|
||||
cdkDropListSortingDisabled
|
||||
>
|
||||
<div class="languages-top-row">
|
||||
<span class="label">{{ 'SETTING.LANGUAGES.NOT_ALLOWED' | translate }}</span>
|
||||
<button
|
||||
class="list-button"
|
||||
[disabled]="(canWriteRestrictions$ | async) === false"
|
||||
(click)="disallowAll()"
|
||||
mat-stroked-button
|
||||
>
|
||||
<div class="cnsl-action-button">
|
||||
<i class="las la-object-group"></i><span>{{ 'SETTING.LANGUAGES.DISALLOW_ALL' | translate }}</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="languages-drop-target">
|
||||
<div
|
||||
class="card languages-box"
|
||||
*ngFor="let lang of (localState$ | async)!.notAllowed"
|
||||
[cdkDragData]="lang"
|
||||
cdkDrag
|
||||
[cdkDragDisabled]="(canWriteRestrictions$ | async) === false"
|
||||
mat-list-item
|
||||
>
|
||||
<span class="locale">{{ lang }}</span>
|
||||
<span class="lang">{{ 'SETTING.LANGUAGES.OPTIONS.' + lang | translate }} </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="general-btn-container">
|
||||
<button
|
||||
class="reset-button"
|
||||
[disabled]="(canWriteRestrictions$ | async) === false"
|
||||
(click)="discard()"
|
||||
color="message-text-warn"
|
||||
mat-stroked-button
|
||||
>
|
||||
<div class="cnsl-action-button">
|
||||
<i class="las la-history"></i><span>{{ 'ACTIONS.UNSAVED.DIALOG.DISCARD' | translate }}</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="save-button"
|
||||
color="primary"
|
||||
type="submit"
|
||||
(click)="submit()"
|
||||
mat-raised-button
|
||||
[disabled]="(canWriteRestrictions$ | async) === false"
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
@ -0,0 +1,112 @@
|
||||
.languages-container-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
column-gap: 2rem;
|
||||
|
||||
@media only screen and (max-width: 700px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.languages-container {
|
||||
display: inline-block;
|
||||
max-width: 400px;
|
||||
vertical-align: top;
|
||||
width: 100%;
|
||||
|
||||
.spinner-wr {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.default-language {
|
||||
max-width: 400px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.general-btn-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 1rem;
|
||||
|
||||
.save-button {
|
||||
display: block;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.languages-list {
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
height: 100%;
|
||||
|
||||
.languages-top-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 1.5rem;
|
||||
|
||||
.label {
|
||||
margin-right: 1rem;
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.list-button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.languages-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.5rem 0.5rem 0.5rem 2rem;
|
||||
height: 56px;
|
||||
cursor: move;
|
||||
margin: 2px 0;
|
||||
|
||||
.index {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
opacity: 0.5;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.locale {
|
||||
width: 35px;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.lang {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
[hoveractions] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.more-button {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
[hoveractions] {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.defaultlanglabel {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
@ -1,19 +1,19 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GeneralSettingsComponent } from './general-settings.component';
|
||||
import { LanguageSettingsComponent } from './language-settings.component';
|
||||
|
||||
describe('GeneralSettingsComponent', () => {
|
||||
let component: GeneralSettingsComponent;
|
||||
let fixture: ComponentFixture<GeneralSettingsComponent>;
|
||||
describe('LanguageSettingsComponent', () => {
|
||||
let component: LanguageSettingsComponent;
|
||||
let fixture: ComponentFixture<LanguageSettingsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [GeneralSettingsComponent],
|
||||
declarations: [LanguageSettingsComponent],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(GeneralSettingsComponent);
|
||||
fixture = TestBed.createComponent(LanguageSettingsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
@ -0,0 +1,116 @@
|
||||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { UntypedFormBuilder } from '@angular/forms';
|
||||
import { LanguagesService } from '../../../services/languages.service';
|
||||
import { BehaviorSubject, concat, forkJoin, from, Observable, of, Subject, switchMap, take, takeUntil } from 'rxjs';
|
||||
import { GrpcAuthService } from '../../../services/grpc-auth.service';
|
||||
import { CdkDrag, CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
|
||||
interface State {
|
||||
allowed: string[];
|
||||
notAllowed: string[];
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-language-settings',
|
||||
templateUrl: './language-settings.component.html',
|
||||
styleUrls: ['./language-settings.component.scss'],
|
||||
})
|
||||
export class LanguageSettingsComponent {
|
||||
public canWriteRestrictions$: Observable<boolean> = this.authService.isAllowed(['iam.restrictions.write']);
|
||||
public canWriteDefaultLanguage$: Observable<boolean> = this.authService.isAllowed(['iam.write']);
|
||||
|
||||
public localState$ = new BehaviorSubject<State>({ allowed: [], notAllowed: [] });
|
||||
public remoteState$ = new BehaviorSubject<State>({ allowed: [], notAllowed: [] });
|
||||
public defaultLang$ = new BehaviorSubject<string>('');
|
||||
|
||||
public loading: boolean = false;
|
||||
constructor(
|
||||
private service: AdminService,
|
||||
private toast: ToastService,
|
||||
private langSvc: LanguagesService,
|
||||
private authService: GrpcAuthService,
|
||||
) {
|
||||
const sub = forkJoin([
|
||||
langSvc.allowed$.pipe(take(1)),
|
||||
langSvc.notAllowed$.pipe(take(1)),
|
||||
from(this.service.getDefaultLanguage()).pipe(take(1)),
|
||||
]).subscribe({
|
||||
next: ([allowed, notAllowed, { language: defaultLang }]) => {
|
||||
this.defaultLang$.next(defaultLang);
|
||||
this.remoteState$.next({ notAllowed: [...notAllowed], ...{ allowed: [...allowed] } });
|
||||
this.localState$.next({ notAllowed: [...notAllowed], ...{ allowed: [...allowed] } });
|
||||
},
|
||||
error: this.toast.showError,
|
||||
complete: () => {
|
||||
sub.unsubscribe();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
drop(event: CdkDragDrop<string[]>) {
|
||||
if (event.previousContainer === event.container) {
|
||||
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
|
||||
} else {
|
||||
transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public defaultLangPredicate = (lang: CdkDrag<string>) => {
|
||||
return !!lang?.data && lang.data !== this.defaultLang$.value;
|
||||
};
|
||||
|
||||
public isRemotelyAllowed$(lang: string): Observable<boolean> {
|
||||
return this.remoteState$.pipe(map(({ allowed }) => allowed.includes(lang)));
|
||||
}
|
||||
|
||||
public allowAll(): void {
|
||||
this.localState$.next({ allowed: [...this.allLocalLangs()], notAllowed: [] });
|
||||
}
|
||||
|
||||
public disallowAll(): void {
|
||||
const disallowed = this.allLocalLangs().filter((lang) => lang !== this.defaultLang$.value);
|
||||
this.localState$.next({ allowed: [this.defaultLang$.value], notAllowed: disallowed });
|
||||
}
|
||||
|
||||
public submit(): void {
|
||||
const { allowed, notAllowed } = this.localState$.value;
|
||||
const sub = from(this.service.setRestrictions(undefined, allowed)).subscribe({
|
||||
next: () => {
|
||||
this.remoteState$.next({
|
||||
allowed: [...allowed],
|
||||
notAllowed: [...notAllowed],
|
||||
});
|
||||
this.langSvc.newAllowed(allowed);
|
||||
this.toast.showInfo('SETTING.LANGUAGES.ALLOWED_SAVED', true);
|
||||
},
|
||||
error: this.toast.showError,
|
||||
complete: () => {
|
||||
sub.unsubscribe();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public discard(): void {
|
||||
this.localState$.next(this.remoteState$.value);
|
||||
}
|
||||
|
||||
public setDefaultLang(lang: string): void {
|
||||
const sub = from(this.service.setDefaultLanguage(lang)).subscribe({
|
||||
next: () => {
|
||||
this.defaultLang$.next(lang);
|
||||
this.toast.showInfo('SETTING.LANGUAGES.DEFAULT_SAVED', true);
|
||||
},
|
||||
error: this.toast.showError,
|
||||
complete: () => {
|
||||
sub.unsubscribe();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private allLocalLangs(): string[] {
|
||||
return [...this.localState$.value.allowed, ...this.localState$.value.notAllowed];
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { CardModule } from '../../card/card.module';
|
||||
import { FormFieldModule } from '../../form-field/form-field.module';
|
||||
import { LanguageSettingsComponent } from './language-settings.component';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||
import { MatRadioModule } from '@angular/material/radio';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TableActionsModule } from '../../table-actions/table-actions.module';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
|
||||
@NgModule({
|
||||
declarations: [LanguageSettingsComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
CardModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatFormFieldModule,
|
||||
MatButtonModule,
|
||||
MatSelectModule,
|
||||
FormFieldModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSelectModule,
|
||||
HasRolePipeModule,
|
||||
TranslateModule,
|
||||
MatListModule,
|
||||
DragDropModule,
|
||||
MatRadioModule,
|
||||
MatTooltipModule,
|
||||
MatMenuModule,
|
||||
MatIconModule,
|
||||
],
|
||||
exports: [LanguageSettingsComponent],
|
||||
})
|
||||
export class LanguageSettingsModule {}
|
@ -242,14 +242,20 @@
|
||||
| async) === false
|
||||
"
|
||||
>
|
||||
{{ 'POLICY.DATA.ALLOWREGISTER' | translate }}
|
||||
{{ 'POLICY.DATA.ALLOWREGISTERUSERS' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="login-policy-row">
|
||||
<mat-checkbox
|
||||
class="login-policy-toggle"
|
||||
color="primary"
|
||||
ngDefaultControl
|
||||
[(ngModel)]="allowOrgRegistration"
|
||||
*ngIf="serviceType === PolicyComponentServiceType.ADMIN"
|
||||
[disabled]="(['iam.restrictions.write'] | hasRole | async) === false"
|
||||
>
|
||||
{{ 'POLICY.DATA.ALLOWREGISTERORGS' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<!-- <ng-template #regInfo>
|
||||
<cnsl-info-section class="info">
|
||||
{{ 'POLICY.DATA.ALLOWREGISTER_DESC' | translate }}
|
||||
</cnsl-info-section>
|
||||
</ng-template> -->
|
||||
</div>
|
||||
<div class="login-policy-row">
|
||||
<mat-checkbox
|
||||
@ -428,6 +434,7 @@
|
||||
type="submit"
|
||||
mat-raised-button
|
||||
[disabled]="
|
||||
(['iam.restrictions.write'] | hasRole | async) === false &&
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Component, Injector, Input, OnInit, Type } from '@angular/core';
|
||||
import { Component, Injector, Input, OnDestroy, OnInit, Type } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
import { take } from 'rxjs';
|
||||
import { firstValueFrom, forkJoin, from, Observable, of, Subject, take } from 'rxjs';
|
||||
import {
|
||||
GetLoginPolicyResponse as AdminGetLoginPolicyResponse,
|
||||
UpdateLoginPolicyRequest,
|
||||
@ -24,19 +24,21 @@ import { InfoSectionType } from '../../info-section/info-section.component';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { LoginMethodComponentType } from './factor-table/factor-table.component';
|
||||
import { catchError, map, takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-login-policy',
|
||||
templateUrl: './login-policy.component.html',
|
||||
styleUrls: ['./login-policy.component.scss'],
|
||||
})
|
||||
export class LoginPolicyComponent implements OnInit {
|
||||
export class LoginPolicyComponent implements OnInit, OnDestroy {
|
||||
public LoginMethodComponentType: any = LoginMethodComponentType;
|
||||
public passwordlessTypes: Array<PasswordlessType> = [
|
||||
PasswordlessType.PASSWORDLESS_TYPE_NOT_ALLOWED,
|
||||
PasswordlessType.PASSWORDLESS_TYPE_ALLOWED,
|
||||
];
|
||||
public loginData?: LoginPolicy.AsObject;
|
||||
public allowOrgRegistration: boolean = false;
|
||||
|
||||
public service!: ManagementService | AdminService;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
@ -52,6 +54,8 @@ export class LoginPolicyComponent implements OnInit {
|
||||
secondFactorCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
multiFactorCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
});
|
||||
private destroy$: Subject<void> = new Subject();
|
||||
|
||||
constructor(
|
||||
private toast: ToastService,
|
||||
private injector: Injector,
|
||||
@ -60,43 +64,59 @@ export class LoginPolicyComponent implements OnInit {
|
||||
private dialog: MatDialog,
|
||||
) {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
public fetchData(): void {
|
||||
this.getData()
|
||||
.then((resp) => {
|
||||
if (resp.policy) {
|
||||
this.loginData = resp.policy;
|
||||
this.loading = false;
|
||||
const data$ = forkJoin([
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
? from((this.service as AdminService).getRestrictions()).pipe(
|
||||
map(({ disallowPublicOrgRegistration }) => disallowPublicOrgRegistration),
|
||||
)
|
||||
: of(true),
|
||||
from(this.getData()),
|
||||
]);
|
||||
|
||||
this.passwordCheckLifetime?.setValue(
|
||||
this.loginData.passwordCheckLifetime?.seconds ? this.loginData.passwordCheckLifetime?.seconds / 60 / 60 : 0,
|
||||
);
|
||||
|
||||
this.externalLoginCheckLifetime?.setValue(
|
||||
this.loginData.externalLoginCheckLifetime?.seconds
|
||||
? this.loginData.externalLoginCheckLifetime?.seconds / 60 / 60
|
||||
: 0,
|
||||
);
|
||||
|
||||
this.mfaInitSkipLifetime?.setValue(
|
||||
this.loginData.mfaInitSkipLifetime?.seconds ? this.loginData.mfaInitSkipLifetime?.seconds / 60 / 60 : 0,
|
||||
);
|
||||
|
||||
this.secondFactorCheckLifetime?.setValue(
|
||||
this.loginData.secondFactorCheckLifetime?.seconds
|
||||
? this.loginData.secondFactorCheckLifetime?.seconds / 60 / 60
|
||||
: 0,
|
||||
);
|
||||
|
||||
this.multiFactorCheckLifetime?.setValue(
|
||||
this.loginData.multiFactorCheckLifetime?.seconds
|
||||
? this.loginData.multiFactorCheckLifetime?.seconds / 60 / 60
|
||||
: 0,
|
||||
);
|
||||
const sub = data$.pipe(takeUntil(this.destroy$)).subscribe({
|
||||
next: ([disallowPublicOrgRegistration, resp]) => {
|
||||
this.allowOrgRegistration = !disallowPublicOrgRegistration;
|
||||
if (!resp.policy) {
|
||||
return;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
this.loginData = resp.policy;
|
||||
this.loading = false;
|
||||
|
||||
this.passwordCheckLifetime?.setValue(
|
||||
this.loginData.passwordCheckLifetime?.seconds ? this.loginData.passwordCheckLifetime?.seconds / 60 / 60 : 0,
|
||||
);
|
||||
|
||||
this.externalLoginCheckLifetime?.setValue(
|
||||
this.loginData.externalLoginCheckLifetime?.seconds
|
||||
? this.loginData.externalLoginCheckLifetime?.seconds / 60 / 60
|
||||
: 0,
|
||||
);
|
||||
|
||||
this.mfaInitSkipLifetime?.setValue(
|
||||
this.loginData.mfaInitSkipLifetime?.seconds ? this.loginData.mfaInitSkipLifetime?.seconds / 60 / 60 : 0,
|
||||
);
|
||||
|
||||
this.secondFactorCheckLifetime?.setValue(
|
||||
this.loginData.secondFactorCheckLifetime?.seconds
|
||||
? this.loginData.secondFactorCheckLifetime?.seconds / 60 / 60
|
||||
: 0,
|
||||
);
|
||||
|
||||
this.multiFactorCheckLifetime?.setValue(
|
||||
this.loginData.multiFactorCheckLifetime?.seconds ? this.loginData.multiFactorCheckLifetime?.seconds / 60 / 60 : 0,
|
||||
);
|
||||
},
|
||||
error: this.toast.showError,
|
||||
complete: () => {
|
||||
sub.unsubscribe();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
@ -142,7 +162,9 @@ export class LoginPolicyComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
private async updateData(): Promise<UpdateLoginPolicyResponse.AsObject> {
|
||||
private async updateData(): Promise<any> {
|
||||
const calls: Observable<any>[] = [];
|
||||
|
||||
if (this.loginData) {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
@ -179,7 +201,8 @@ export class LoginPolicyComponent implements OnInit {
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
return (this.service as ManagementService).addCustomLoginPolicy(mgmtreq);
|
||||
calls.push(from((this.service as ManagementService).addCustomLoginPolicy(mgmtreq)));
|
||||
break;
|
||||
} else {
|
||||
const mgmtreq = new UpdateCustomLoginPolicyRequest();
|
||||
mgmtreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
@ -211,7 +234,8 @@ export class LoginPolicyComponent implements OnInit {
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
return (this.service as ManagementService).updateCustomLoginPolicy(mgmtreq);
|
||||
calls.push(from((this.service as ManagementService).updateCustomLoginPolicy(mgmtreq)));
|
||||
break;
|
||||
}
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
const adminreq = new UpdateLoginPolicyRequest();
|
||||
@ -243,11 +267,21 @@ export class LoginPolicyComponent implements OnInit {
|
||||
adminreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
adminreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
return (this.service as AdminService).updateLoginPolicy(adminreq);
|
||||
calls.push(from((this.service as AdminService).setRestrictions(!this.allowOrgRegistration)));
|
||||
calls.push(from((this.service as AdminService).updateLoginPolicy(adminreq)));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return Promise.reject();
|
||||
calls.push(from(Promise.reject()));
|
||||
}
|
||||
return firstValueFrom(
|
||||
forkJoin(calls).pipe(
|
||||
catchError((error, caught) => {
|
||||
// We just ignore the policy not changed error!
|
||||
return (error as { message: string }).message.includes('INSTANCE-5M9vdd') ? of(true) : caught;
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
|
@ -6,9 +6,6 @@
|
||||
[settingsList]="settingsList"
|
||||
queryParam="id"
|
||||
>
|
||||
<ng-container *ngIf="currentSetting === 'general' && serviceType === PolicyComponentServiceType.ADMIN">
|
||||
<cnsl-general-settings></cnsl-general-settings>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="currentSetting === 'complexity'">
|
||||
<cnsl-password-complexity-policy [serviceType]="serviceType"></cnsl-password-complexity-policy>
|
||||
</ng-container>
|
||||
@ -57,4 +54,7 @@
|
||||
<ng-container *ngIf="currentSetting === 'privacypolicy'">
|
||||
<cnsl-privacy-policy [serviceType]="serviceType"></cnsl-privacy-policy>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="currentSetting === 'languages' && serviceType === PolicyComponentServiceType.ADMIN">
|
||||
<cnsl-language-settings></cnsl-language-settings>
|
||||
</ng-container>
|
||||
</cnsl-sidenav>
|
||||
|
@ -7,7 +7,7 @@ import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.mod
|
||||
import { CardModule } from '../card/card.module';
|
||||
import DomainsModule from '../domains/domains.module';
|
||||
import { DomainPolicyModule } from '../policies/domain-policy/domain-policy.module';
|
||||
import { GeneralSettingsModule } from '../policies/general-settings/general-settings.module';
|
||||
import { LanguageSettingsModule } from '../policies/language-settings/language-settings.module';
|
||||
import { IdpSettingsModule } from '../policies/idp-settings/idp-settings.module';
|
||||
import { LoginPolicyModule } from '../policies/login-policy/login-policy.module';
|
||||
import { LoginTextsPolicyModule } from '../policies/login-texts/login-texts.module';
|
||||
@ -36,7 +36,7 @@ import { SettingsListComponent } from './settings-list.component';
|
||||
PasswordComplexityPolicyModule,
|
||||
PasswordLockoutPolicyModule,
|
||||
PrivateLabelingPolicyModule,
|
||||
GeneralSettingsModule,
|
||||
LanguageSettingsModule,
|
||||
NotificationPolicyModule,
|
||||
IdpSettingsModule,
|
||||
PrivacyPolicyModule,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
|
||||
import { SidenavSetting } from '../sidenav/sidenav.component';
|
||||
|
||||
export const GENERAL: SidenavSetting = {
|
||||
id: 'general',
|
||||
i18nKey: 'SETTINGS.LIST.GENERAL',
|
||||
export const LANGUAGES: SidenavSetting = {
|
||||
id: 'languages',
|
||||
i18nKey: 'SETTINGS.LIST.LANGUAGES',
|
||||
requiredRoles: {
|
||||
[PolicyComponentServiceType.ADMIN]: ['iam.policy.read'],
|
||||
},
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
BRANDING,
|
||||
COMPLEXITY,
|
||||
DOMAIN,
|
||||
GENERAL,
|
||||
LANGUAGES,
|
||||
IDP,
|
||||
LOCKOUT,
|
||||
LOGIN,
|
||||
@ -34,7 +34,6 @@ export class InstanceSettingsComponent implements OnInit, OnDestroy {
|
||||
public id: string = '';
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public defaultSettingsList: SidenavSetting[] = [
|
||||
GENERAL,
|
||||
// notifications
|
||||
// { showWarn: true, ...NOTIFICATIONS },
|
||||
NOTIFICATIONS,
|
||||
@ -53,6 +52,7 @@ export class InstanceSettingsComponent implements OnInit, OnDestroy {
|
||||
LOGINTEXTS,
|
||||
// others
|
||||
PRIVACYPOLICY,
|
||||
LANGUAGES,
|
||||
OIDC,
|
||||
SECRETS,
|
||||
SECURITY,
|
||||
|
@ -128,6 +128,7 @@ import {
|
||||
GetPrivacyPolicyResponse,
|
||||
GetProviderByIDRequest,
|
||||
GetProviderByIDResponse,
|
||||
GetRestrictionsResponse,
|
||||
GetSecretGeneratorRequest,
|
||||
GetSecretGeneratorResponse,
|
||||
GetSecurityPolicyRequest,
|
||||
@ -194,6 +195,7 @@ import {
|
||||
ResetCustomDomainPolicyToDefaultResponse,
|
||||
ResetCustomLoginTextsToDefaultRequest,
|
||||
ResetCustomLoginTextsToDefaultResponse,
|
||||
SelectLanguages,
|
||||
SetCustomLoginTextsRequest,
|
||||
SetCustomLoginTextsResponse,
|
||||
SetDefaultDomainClaimedMessageTextRequest,
|
||||
@ -218,6 +220,8 @@ import {
|
||||
SetDefaultVerifyPhoneMessageTextResponse,
|
||||
SetDefaultVerifySMSOTPMessageTextRequest,
|
||||
SetDefaultVerifySMSOTPMessageTextResponse,
|
||||
SetRestrictionsRequest,
|
||||
SetRestrictionsResponse,
|
||||
SetSecurityPolicyRequest,
|
||||
SetSecurityPolicyResponse,
|
||||
SetUpOrgRequest,
|
||||
@ -830,6 +834,29 @@ export class AdminService {
|
||||
return this.grpcService.admin.setDefaultLanguage(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
/* restrictions */
|
||||
|
||||
public getRestrictions(): Promise<GetRestrictionsResponse.AsObject> {
|
||||
const req = new GetDefaultLanguageRequest();
|
||||
return this.grpcService.admin.getRestrictions(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public setRestrictions(
|
||||
disallowPublicOrgRegistration?: boolean,
|
||||
allowedLanguages?: string[],
|
||||
): Promise<SetRestrictionsResponse.AsObject> {
|
||||
const req = new SetRestrictionsRequest();
|
||||
if (disallowPublicOrgRegistration !== undefined) {
|
||||
req.setDisallowPublicOrgRegistration(disallowPublicOrgRegistration);
|
||||
}
|
||||
if (allowedLanguages !== undefined) {
|
||||
const langs = new SelectLanguages();
|
||||
langs.setListList(allowedLanguages);
|
||||
req.setAllowedLanguages(langs);
|
||||
}
|
||||
return this.grpcService.admin.setRestrictions(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
/* notification policy */
|
||||
|
||||
public getNotificationPolicy(): Promise<GetNotificationPolicyResponse.AsObject> {
|
||||
|
@ -36,7 +36,6 @@ export class LanguagesService {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: call this in https://github.com/zitadel/zitadel/pull/6965
|
||||
public newAllowed(languages: string[]) {
|
||||
this.allowedSubject$.next(languages);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ export class ToastService {
|
||||
}
|
||||
}
|
||||
|
||||
public showError(error: any | string, isGrpc: boolean = true, i18nKey: boolean = false): void {
|
||||
public showError = (error: any | string, isGrpc: boolean = true, i18nKey: boolean = false) => {
|
||||
if (isGrpc) {
|
||||
const { message, code, metadata } = error;
|
||||
if (code !== 16) {
|
||||
@ -57,7 +57,7 @@ export class ToastService {
|
||||
} else {
|
||||
this.showMessage(error as string, '', false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private showMessage(message: string, action: string, success: boolean): Observable<void> {
|
||||
const ref = this.snackBar.open(message, action, {
|
||||
|
@ -1014,7 +1014,7 @@
|
||||
"DESCRIPTION": "Тези настройки разширяват и презаписват настройките на вашия екземпляр."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Общ",
|
||||
"LANGUAGES": "Езици",
|
||||
"LOGIN": "Поведение при влизане и сигурност",
|
||||
"LOCKOUT": "Блокиране",
|
||||
"COMPLEXITY": "Сложност на паролата",
|
||||
@ -1043,22 +1043,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Език по подразбиране",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "Английски",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Италиано",
|
||||
"ja": "日本語",
|
||||
"pl": "Полски",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Настройки на езика",
|
||||
"DEFAULT": "Език по подразбиране",
|
||||
"ALLOWED": "Разрешени езици",
|
||||
"NOT_ALLOWED": "Не са разрешени езици",
|
||||
"ALLOW_ALL": "Разрешете всички езици",
|
||||
"DISALLOW_ALL": "Забранете всички езици",
|
||||
"SETASDEFAULT": "Задайте като език по подразбиране",
|
||||
"DEFAULT_SAVED": "Езикът по подразбиране е запазен успешно.",
|
||||
"ALLOWED_SAVED": "Разрешените езици са запазени успешно.",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "Английски",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Италиано",
|
||||
"ja": "日本語",
|
||||
"pl": "Полски",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP настройки",
|
||||
@ -1371,7 +1381,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "SMTP адресът на изпращача съвпада с домейна на екземпляра",
|
||||
"ALLOWUSERNAMEPASSWORD": "Потребителско име Паролата е разрешена",
|
||||
"ALLOWEXTERNALIDP": "Допуска се външен IDP",
|
||||
"ALLOWREGISTER": "Регистрацията е разрешена",
|
||||
"ALLOWREGISTERUSERS": "Регистрирайте потребители",
|
||||
"ALLOWREGISTERORGS": "Регистрирайте организации",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Разрешено е конвенционалното влизане с потребителско име и парола.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Входът е разрешен за основните доставчици на самоличност",
|
||||
"ALLOWREGISTER_DESC": "Ако опцията е избрана, в входа се появява допълнителна стъпка за регистрация на потребител.",
|
||||
|
@ -1021,7 +1021,7 @@
|
||||
"DESCRIPTION": "Tato nastavení rozšiřují a přepisují nastavení vaší instance."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Obecné",
|
||||
"LANGUAGES": "Jazyky",
|
||||
"LOGIN": "Chování při přihlášení a bezpečnost",
|
||||
"LOCKOUT": "Blokování",
|
||||
"COMPLEXITY": "Složitost hesla",
|
||||
@ -1050,22 +1050,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Výchozí jazyk",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Nastavení jazyka",
|
||||
"DEFAULT": "Výchozí jazyk",
|
||||
"ALLOWED": "Povolené jazyky",
|
||||
"NOT_ALLOWED": "Nepovolené jazyky",
|
||||
"ALLOW_ALL": "Povolit všechny jazyky",
|
||||
"DISALLOW_ALL": "Zakázat všechny jazyky",
|
||||
"SETASDEFAULT": "Nastavit jako výchozí",
|
||||
"DEFAULT_SAVED": "Výchozí jazyk byl úspěšně nastaven.",
|
||||
"ALLOWED_SAVED": "Povolené jazyky byly úspěšně nastaveny.",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Nastavení SMTP",
|
||||
@ -1379,6 +1389,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD": "Povoleno uživatelské jméno a heslo",
|
||||
"ALLOWEXTERNALIDP": "Povoleno externí IDP",
|
||||
"ALLOWREGISTER": "Registrace povolena",
|
||||
"ALLOWREGISTERUSERS": "Registrace uživatelů povolena",
|
||||
"ALLOWREGISTERORGS": "Registrace organizací povolena",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Je povoleno klasické přihlášení s uživatelským jménem a heslem.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Přihlášení je povoleno pro níže uvedené poskytovatele identity.",
|
||||
"ALLOWREGISTER_DESC": "Pokud je možnost vybrána, objeví se při přihlášení další krok pro registraci uživatele.",
|
||||
|
@ -1020,7 +1020,7 @@
|
||||
"DESCRIPTION": "Diese Einstellungen erweitern bzw. überschreiben die Einstellungen Ihrer Instanz."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Allgemein",
|
||||
"LANGUAGES": "Sprachen",
|
||||
"LOGIN": "Loginverhalten und Sicherheit",
|
||||
"LOCKOUT": "Sperrmechanismen",
|
||||
"COMPLEXITY": "Passwordkomplexität",
|
||||
@ -1049,22 +1049,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Standardsprache",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Spracheinstellungen",
|
||||
"DEFAULT": "Standardsprache",
|
||||
"ALLOWED": "Erlaubte Sprachen",
|
||||
"NOT_ALLOWED": "Nicht erlaubte Sprachen",
|
||||
"ALLOW_ALL": "Alle Sprachen erlauben",
|
||||
"DISALLOW_ALL": "Alle Sprachen verbieten",
|
||||
"SETASDEFAULT": "Als Standard setzen",
|
||||
"DEFAULT_SAVED": "Standard Sprache gesetzt",
|
||||
"ALLOWED_SAVED": "Erlaubte Sprachen gesetzt",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP Einstellungen",
|
||||
@ -1377,7 +1387,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "SMTP Sender Adresse entspricht Instanzdomain",
|
||||
"ALLOWUSERNAMEPASSWORD": "Benutzername Passwort erlaubt",
|
||||
"ALLOWEXTERNALIDP": "Externer IDP erlaubt",
|
||||
"ALLOWREGISTER": "Registrieren erlaubt",
|
||||
"ALLOWREGISTERUSERS": "Benutzerregistrierung erlaubt",
|
||||
"ALLOWREGISTERORGS": "Organisationsregistrierung erlaubt",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Der konventionelle Login mit Benutzername und Passwort wird erlaubt.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Der Login wird für die darunter liegenden Identitätsanbieter erlaubt.",
|
||||
"ALLOWREGISTER_DESC": "Ist die Option gewählt, erscheint im Login ein zusätzlicher Schritt zum Registrieren eines Benutzers.",
|
||||
|
@ -1021,7 +1021,7 @@
|
||||
"DESCRIPTION": "These settings extend and overwrite your instance settings."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "General",
|
||||
"LANGUAGES": "Languages",
|
||||
"LOGIN": "Login Behavior and Security",
|
||||
"LOCKOUT": "Lockout",
|
||||
"COMPLEXITY": "Password complexity",
|
||||
@ -1050,22 +1050,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Default Language",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Language Settings",
|
||||
"DEFAULT": "Default Language",
|
||||
"ALLOWED": "Allowed Languages",
|
||||
"NOT_ALLOWED": "Not Allowed Languages",
|
||||
"ALLOW_ALL": "Allow All",
|
||||
"DISALLOW_ALL": "Disallow All",
|
||||
"SETASDEFAULT": "Set as Default Language",
|
||||
"DEFAULT_SAVED": "Default Language saved",
|
||||
"ALLOWED_SAVED": "Allowed Languages saved",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP Settings",
|
||||
@ -1378,7 +1388,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "SMTP Sender Address matches Instance Domain",
|
||||
"ALLOWUSERNAMEPASSWORD": "Username Password allowed",
|
||||
"ALLOWEXTERNALIDP": "External IDP allowed",
|
||||
"ALLOWREGISTER": "Register allowed",
|
||||
"ALLOWREGISTERUSERS": "Register users allowed",
|
||||
"ALLOWREGISTERORGS": "Register organizations allowed",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "The conventional login with user name and password is allowed.",
|
||||
"ALLOWEXTERNALIDP_DESC": "The login is allowed for the underlying identity providers",
|
||||
"ALLOWREGISTER_DESC": "If the option is selected, an additional step for registering a user appears in the login.",
|
||||
|
@ -1021,7 +1021,7 @@
|
||||
"DESCRIPTION": "Estas configuraciones amplían y sobrescriben tus configuraciones de instancia."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "General",
|
||||
"LANGUAGES": "Idiomas",
|
||||
"LOGIN": "Comportamiento del inicio de sesión y de la seguridad",
|
||||
"LOCKOUT": "Bloqueo",
|
||||
"COMPLEXITY": "Complejidad de contraseña",
|
||||
@ -1050,22 +1050,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Idioma por defecto",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Ajustes de idioma",
|
||||
"DEFAULT": "Idioma predeterminado",
|
||||
"ALLOWED": "Idiomas permitidos",
|
||||
"NOT_ALLOWED": "Idiomas no permitidos",
|
||||
"ALLOW_ALL": "Permitir todos los idiomas",
|
||||
"DISALLOW_ALL": "No permitir ningún idioma",
|
||||
"SETASDEFAULT": "Establecer como idioma predeterminado",
|
||||
"DEFAULT_SAVED": "Idioma predeterminado guardado",
|
||||
"ALLOWED_SAVED": "Idiomas permitidos guardados",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Ajustes SMTP",
|
||||
@ -1378,7 +1388,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "La dirección del remitente SMTP coincide con el dominio de la instancia",
|
||||
"ALLOWUSERNAMEPASSWORD": "Nombre de usuario y contraseña permitido",
|
||||
"ALLOWEXTERNALIDP": "Permitido IDP externo",
|
||||
"ALLOWREGISTER": "Registro permitido",
|
||||
"ALLOWREGISTERUSERS": "Registro de usuarios permitido",
|
||||
"ALLOWREGISTERORGS": "Registro de organizaciones permitido",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "El inicio de sesión convencional con nombre de usuario y contraseña está permitido.",
|
||||
"ALLOWEXTERNALIDP_DESC": "El inicio de sesión está permitido para los proveedores de identidad subyacentes",
|
||||
"ALLOWREGISTER_DESC": "Si esta opción es seleccionada, aparece un paso adicional durante el inicio de sesión para registrar un usuario.",
|
||||
|
@ -1020,7 +1020,7 @@
|
||||
"DESCRIPTION": "Ces paramètres étendent et remplacent les paramètres de votre instance."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Général",
|
||||
"LANGUAGES": "Langues",
|
||||
"LOGIN": "Comportement de connexion et sécurité",
|
||||
"LOCKOUT": "Verrouillage",
|
||||
"COMPLEXITY": "Complexité du mot de passe",
|
||||
@ -1049,22 +1049,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Langue par défaut",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Paramètres de langue",
|
||||
"DEFAULT": "Langue par défaut",
|
||||
"ALLOWED": "Langues autorisées",
|
||||
"NOT_ALLOWED": "Langues non autorisées",
|
||||
"ALLOW_ALL": "Autoriser toutes les langues",
|
||||
"DISALLOW_ALL": "Interdire toutes les langues",
|
||||
"SETASDEFAULT": "Définir comme langue par défaut",
|
||||
"DEFAULT_SAVED": "Langue par défaut enregistrée",
|
||||
"ALLOWED_SAVED": "Langues autorisées enregistrées",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Paramètres SMTP",
|
||||
@ -1377,7 +1387,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "L'adresse de l'expéditeur SMTP correspond au domaine de l'instance",
|
||||
"ALLOWUSERNAMEPASSWORD": "Nom d'utilisateur Mot de passe autorisé",
|
||||
"ALLOWEXTERNALIDP": "IDP externe autorisé",
|
||||
"ALLOWREGISTER": "Enregistrement autorisé",
|
||||
"ALLOWREGISTERUSERS": "Enregistrer les utilisateurs autorisés",
|
||||
"ALLOWREGISTERORGS": "Enregistrer les organisations autorisées",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "La connexion classique avec nom d'utilisateur et mot de passe est autorisée.",
|
||||
"ALLOWEXTERNALIDP_DESC": "La connexion est autorisée pour les fournisseurs d'identité sous-jacents",
|
||||
"ALLOWREGISTER_DESC": "Si l'option est sélectionnée, une étape supplémentaire pour l'enregistrement d'un utilisateur apparaît dans la connexion.",
|
||||
|
@ -1020,7 +1020,7 @@
|
||||
"DESCRIPTION": "Queste impostazioni si applicheranno alla organizzazione corrente."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Generale",
|
||||
"LANGUAGES": "Lingue",
|
||||
"LOGIN": "Comportamento login e sicurezza",
|
||||
"LOCKOUT": "Meccanismi di bloccaggio",
|
||||
"COMPLEXITY": "Complessità della password",
|
||||
@ -1049,22 +1049,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Lingua standard",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Impostazioni della lingua",
|
||||
"DEFAULT": "Lingua predefinita",
|
||||
"ALLOWED": "Lingue consentite",
|
||||
"NOT_ALLOWED": "Lingue non consentite",
|
||||
"ALLOW_ALL": "Consenti tutte le lingue",
|
||||
"DISALLOW_ALL": "Non consentire tutte le lingue",
|
||||
"SETASDEFAULT": "Imposta come lingua predefinita",
|
||||
"DEFAULT_SAVED": "Lingua predefinita salvata",
|
||||
"ALLOWED_SAVED": "Lingue consentite salvate",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Impostazioni SMTP",
|
||||
@ -1377,7 +1387,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "L'indirizzo mittente SMTP corrisponde al dominio dell'istanza",
|
||||
"ALLOWUSERNAMEPASSWORD": "Autenticazione classica con password consentita",
|
||||
"ALLOWEXTERNALIDP": "IDP esterno consentito",
|
||||
"ALLOWREGISTER": "Registrazione consentita",
|
||||
"ALLOWREGISTERUSERS": "Registrazione utenti consentita",
|
||||
"ALLOWREGISTERORGS": "Registrazione organizzazioni consentita",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Autenticazione classica con nome utente e password \u00e8 permessa.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Il login \u00e8 permesso per gli IDP sottostanti",
|
||||
"ALLOWREGISTER_DESC": "Se l'opzione \u00e8 selezionata, nel login apparirà un passo aggiuntivo per la registrazione di un utente.",
|
||||
|
@ -1021,7 +1021,7 @@
|
||||
"DESCRIPTION": "これらの設定は、インスタンス設定を拡張・上書きします。"
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "全般",
|
||||
"LANGUAGES": "一般設定",
|
||||
"LOGIN": "ログイン動作とセキュリティ",
|
||||
"LOCKOUT": "ロックアウト",
|
||||
"COMPLEXITY": "パスワードの複雑さ",
|
||||
@ -1050,22 +1050,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "デフォルトの言語",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "言語設定",
|
||||
"DEFAULT": "デフォルト言語",
|
||||
"ALLOWED": "許可された言語",
|
||||
"NOT_ALLOWED": "許可されていない言語",
|
||||
"ALLOW_ALL": "すべての言語を許可する",
|
||||
"DISALLOW_ALL": "すべての言語を許可しない",
|
||||
"SETASDEFAULT": "デフォルト言語として設定する",
|
||||
"DEFAULT_SAVED": "デフォルト言語が保存されました",
|
||||
"ALLOWED_SAVED": "許可された言語が保存されました",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP設定",
|
||||
@ -1373,7 +1383,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "SMTP送信者アドレスはインスタンスドメインに一致しています",
|
||||
"ALLOWUSERNAMEPASSWORD": "ユーザー名とパスワードを許可",
|
||||
"ALLOWEXTERNALIDP": "外部IDPを許可",
|
||||
"ALLOWREGISTER": "登録を許可",
|
||||
"ALLOWREGISTERUSERS": "ユーザーの登録を許可",
|
||||
"ALLOWREGISTERORGS": "組織の登録を許可",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "ユーザー名とパスワードを使用した従来のログインを許可します。",
|
||||
"ALLOWEXTERNALIDP_DESC": "基礎となるIDプロバイダーにログインを許可します。",
|
||||
"ALLOWREGISTER_DESC": "このオプションが選択されている場合、ユーザーを登録するための追加のステップがログインに表示されます。",
|
||||
|
@ -1022,7 +1022,7 @@
|
||||
"DESCRIPTION": "Овие подесувања ги прошируваат и препишуваат подесувањата на вашата инстанца."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Генерални",
|
||||
"LANGUAGES": "Општо",
|
||||
"LOGIN": "Правила и безбедност при најава",
|
||||
"LOCKOUT": "Забрана на пристап",
|
||||
"COMPLEXITY": "Сложеност на лозинката",
|
||||
@ -1051,22 +1051,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Стандарден јазик",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Подесувања за јазик",
|
||||
"DEFAULT": "Стандарден јазик",
|
||||
"ALLOWED": "Дозволени јазици",
|
||||
"NOT_ALLOWED": "Не дозволени јазици",
|
||||
"ALLOW_ALL": "Дозволи ги сите јазици",
|
||||
"DISALLOW_ALL": "Забрани ги сите јазици",
|
||||
"SETASDEFAULT": "Постави како стандарден јазик",
|
||||
"DEFAULT_SAVED": "Стандардниот јазик е зачуван",
|
||||
"ALLOWED_SAVED": "Дозволените јазици се зачувани",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP подесувања",
|
||||
@ -1379,7 +1389,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "SMTP адресата на испраќачот се поклопува со доменот на инстанцата",
|
||||
"ALLOWUSERNAMEPASSWORD": "Дозволено корисничко име и лозинка",
|
||||
"ALLOWEXTERNALIDP": "Дозволен надворешен IDP",
|
||||
"ALLOWREGISTER": "Дозволена регистрација",
|
||||
"ALLOWREGISTERUSERS": "Дозволена регистрација на корисници",
|
||||
"ALLOWREGISTERORGS": "Дозволена регистрација на организации",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Дозволена е конвенционална најава со корисничко име и лозинка.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Најавата е дозволена за поддржуваните IDPs",
|
||||
"ALLOWREGISTER_DESC": "Доколку е избрана опцијата, се прикажува дополнителен чекор за регистрирање на корисник во најавата.",
|
||||
|
@ -1021,7 +1021,7 @@
|
||||
"DESCRIPTION": "Deze instellingen breiden uw instantie instellingen uit en overschrijven deze."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Algemeen",
|
||||
"LANGUAGES": "Talen",
|
||||
"LOGIN": "Login Gedrag en Beveiliging",
|
||||
"LOCKOUT": "Lockout",
|
||||
"COMPLEXITY": "Wachtwoord complexiteit",
|
||||
@ -1050,22 +1050,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Standaard Taal",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "Engels",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portugees",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Taalinstellingen",
|
||||
"DEFAULT": "Standaardtaal",
|
||||
"ALLOWED": "Toegestane Talen",
|
||||
"NOT_ALLOWED": "Niet Toegestane Talen",
|
||||
"ALLOW_ALL": "Sta alle talen toe",
|
||||
"DISALLOW_ALL": "Sta geen talen toe",
|
||||
"SETASDEFAULT": "Stel in als standaardtaal",
|
||||
"DEFAULT_SAVED": "Standaardtaal opgeslagen",
|
||||
"ALLOWED_SAVED": "Toegestane talen opgeslagen",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "Engels",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portugees",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP Instellingen",
|
||||
@ -1378,7 +1388,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "SMTP Afzender Adres komt overeen met Instantie Domein",
|
||||
"ALLOWUSERNAMEPASSWORD": "Gebruikersnaam Wachtwoord toegestaan",
|
||||
"ALLOWEXTERNALIDP": "Externe IDP toegestaan",
|
||||
"ALLOWREGISTER": "Registratie toegestaan",
|
||||
"ALLOWREGISTERUSERS": "Gebruikersregistratie toegestaan",
|
||||
"ALLOWREGISTERORGS": "Organisatieregistratie toegestaan",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "De conventionele login met gebruikersnaam en wachtwoord is toegestaan.",
|
||||
"ALLOWEXTERNALIDP_DESC": "De login is toegestaan voor de onderliggende identiteitsproviders",
|
||||
"ALLOWREGISTER_DESC": "Als de optie is geselecteerd, verschijnt er een extra stap voor het registreren van een gebruiker in het login proces.",
|
||||
|
@ -1020,7 +1020,7 @@
|
||||
"DESCRIPTION": "Te ustawienia rozszerzają i nadpisują ustawienia instancji."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Ogólne",
|
||||
"LANGUAGES": "Języki",
|
||||
"LOGIN": "Zachowanie logowania i bezpieczeństwo",
|
||||
"LOCKOUT": "Blokada",
|
||||
"COMPLEXITY": "Złożoność hasła",
|
||||
@ -1049,22 +1049,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Domyślny język",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Ustawienia językowe",
|
||||
"DEFAULT": "Domyślny język",
|
||||
"ALLOWED": "Dozwolone języki",
|
||||
"NOT_ALLOWED": "Niedozwolone języki",
|
||||
"ALLOW_ALL": "Zezwól na wszystkie języki",
|
||||
"DISALLOW_ALL": "Zabroń wszystkich języków",
|
||||
"SETASDEFAULT": "Ustaw jako domyślny język",
|
||||
"DEFAULT_SAVED": "Domyślny język zapisany",
|
||||
"ALLOWED_SAVED": "Dozwolone języki zapisane",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Ustawienia SMTP",
|
||||
@ -1377,7 +1387,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "Adres nadawcy SMTP pasuje do domeny instancji",
|
||||
"ALLOWUSERNAMEPASSWORD": "Zezwól na użycie nazwy użytkownika i hasła",
|
||||
"ALLOWEXTERNALIDP": "Zezwól na zewnętrznego dostawcę tożsamości",
|
||||
"ALLOWREGISTER": "Zezwól na rejestrację",
|
||||
"ALLOWREGISTERUSERS": "Zezwól na rejestrację użytkowników",
|
||||
"ALLOWREGISTERORGS": "Zezwól na rejestrację organizacji",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Zwykłe logowanie za pomocą nazwy użytkownika i hasła jest dozwolone.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Logowanie jest dozwolone dla dostawców tożsamości podstawowych",
|
||||
"ALLOWREGISTER_DESC": "Jeśli ta opcja jest zaznaczona, pojawi się dodatkowy krok rejestracji użytkownika w procesie logowania.",
|
||||
|
@ -1022,7 +1022,7 @@
|
||||
"DESCRIPTION": "Essas configurações estendem e sobrescrevem as configurações da sua instância."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Geral",
|
||||
"LANGUAGES": "Idiomas",
|
||||
"LOGIN": "Comportamento de Login e Segurança",
|
||||
"LOCKOUT": "Bloqueio",
|
||||
"COMPLEXITY": "Complexidade de Senha",
|
||||
@ -1051,22 +1051,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Idioma padrão",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Configurações de Idioma",
|
||||
"DEFAULT": "Idioma Padrão",
|
||||
"ALLOWED": "Idiomas Permitidos",
|
||||
"NOT_ALLOWED": "Idiomas Não Permitidos",
|
||||
"ALLOW_ALL": "Permitir Todos os Idiomas",
|
||||
"DISALLOW_ALL": "Não Permitir Todos os Idiomas",
|
||||
"SETASDEFAULT": "Definir como Idioma Padrão",
|
||||
"DEFAULT_SAVED": "Idioma Padrão salvo",
|
||||
"ALLOWED_SAVED": "Idiomas Permitidos salvos",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Configurações SMTP",
|
||||
@ -1379,7 +1389,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "O endereço do remetente do SMTP corresponde ao domínio da Instância",
|
||||
"ALLOWUSERNAMEPASSWORD": "Permitir usuário e senha",
|
||||
"ALLOWEXTERNALIDP": "Permitir provedor de ID externo",
|
||||
"ALLOWREGISTER": "Permitir registro",
|
||||
"ALLOWREGISTERUSERS": "Permitir registro de usuários",
|
||||
"ALLOWREGISTERORGS": "Permitir registro de organizações",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "O login convencional com nome de usuário e senha é permitido.",
|
||||
"ALLOWEXTERNALIDP_DESC": "O login é permitido para os provedores de identidade subjacentes",
|
||||
"ALLOWREGISTER_DESC": "Se a opção estiver selecionada, uma etapa adicional para registrar um usuário aparecerá no login.",
|
||||
|
@ -1017,7 +1017,7 @@
|
||||
"DESCRIPTION": "Эти настройки расширяют и перезаписывают настройки вашего экземпляра."
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "Общие",
|
||||
"LANGUAGES": "Языки",
|
||||
"LOGIN": "Поведение при входе и безопасность",
|
||||
"LOCKOUT": "Блокировка",
|
||||
"COMPLEXITY": "Сложность пароля",
|
||||
@ -1043,21 +1043,31 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "Язык по умолчанию",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "Настройки языка",
|
||||
"DEFAULT": "Язык по умолчанию",
|
||||
"ALLOWED": "Разрешенные языки",
|
||||
"NOT_ALLOWED": "Неразрешенные языки",
|
||||
"ALLOW_ALL": "Разрешить все языки",
|
||||
"DISALLOW_ALL": "Запретить все языки",
|
||||
"SETASDEFAULT": "Установить как язык по умолчанию",
|
||||
"DEFAULT_SAVED": "Язык по умолчанию сохранен",
|
||||
"ALLOWED_SAVED": "Разрешенные языки сохранены",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "Настройки SMTP",
|
||||
@ -1364,7 +1374,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "Адрес отправителя SMTP соответствует домену экземпляра",
|
||||
"ALLOWUSERNAMEPASSWORD": "Вход с паролем разрешен",
|
||||
"ALLOWEXTERNALIDP": "Внешний поставщик разрешен",
|
||||
"ALLOWREGISTER": "Регистрация разрешена",
|
||||
"ALLOWREGISTERUSERS": "Регистрация пользователей разрешена",
|
||||
"ALLOWREGISTERORGS": "Регистрация организаций разрешена",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Разрешен обычный вход в систему с использованием имени пользователя и паролем.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Вход разрешен для базовых поставщиков удостоверений.",
|
||||
"ALLOWREGISTER_DESC": "Если опция выбрана, в логине появляется дополнительный шаг для регистрации пользователя.",
|
||||
|
@ -1020,7 +1020,7 @@
|
||||
"DESCRIPTION": "这些设置将扩展或覆盖您的实例设置。"
|
||||
},
|
||||
"LIST": {
|
||||
"GENERAL": "通用",
|
||||
"LANGUAGES": "语言",
|
||||
"LOGIN": "登录行为和安全",
|
||||
"LOCKOUT": "安全锁策略",
|
||||
"COMPLEXITY": "密码复杂性",
|
||||
@ -1049,22 +1049,32 @@
|
||||
}
|
||||
},
|
||||
"SETTING": {
|
||||
"DEFAULTLANGUAGE": "默认语言",
|
||||
"LANGUAGE": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
"LANGUAGES": {
|
||||
"TITLE": "语言设置",
|
||||
"DEFAULT": "默认语言",
|
||||
"ALLOWED": "允许的语言",
|
||||
"NOT_ALLOWED": "不允许的语言",
|
||||
"ALLOW_ALL": "允许所有语言",
|
||||
"DISALLOW_ALL": "禁止所有语言",
|
||||
"SETASDEFAULT": "设置为默认语言",
|
||||
"DEFAULT_SAVED": "默认语言已保存",
|
||||
"ALLOWED_SAVED": "允许的语言已保存",
|
||||
"OPTIONS": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"es": "Español",
|
||||
"fr": "Français",
|
||||
"it": "Italiano",
|
||||
"ja": "日本語",
|
||||
"pl": "Polski",
|
||||
"zh": "简体中文",
|
||||
"bg": "Български",
|
||||
"pt": "Portuguese",
|
||||
"mk": "Македонски",
|
||||
"cs": "Čeština",
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
"TITLE": "SMTP 设置",
|
||||
@ -1376,7 +1386,8 @@
|
||||
"SMTPSENDERADDRESSMATCHESINSTANCEDOMAIN": "SMTP 发件人地址与实例域名匹配",
|
||||
"ALLOWUSERNAMEPASSWORD": "允许用户名密码",
|
||||
"ALLOWEXTERNALIDP": "允许外部身份提供者",
|
||||
"ALLOWREGISTER": "允许注册",
|
||||
"ALLOWREGISTERUSERS": "允许注册用户",
|
||||
"ALLOWREGISTERORGS": "允许注册组织",
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "允许使用用户名和密码进行登录。",
|
||||
"ALLOWEXTERNALIDP_DESC": "允许外部身份提供者进行登录",
|
||||
"ALLOWREGISTER_DESC": "如果选择了该选项,登录中会出现一个用于注册用户的附加步骤。",
|
||||
|
@ -49,6 +49,17 @@ ZITADEL is available in the following languages
|
||||
- Russian (ru)
|
||||
- Dutch (nl)
|
||||
|
||||
A language is displayed based on your agent's language header. The default language is English.
|
||||
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.
|
||||
|
||||
If you need support for a specific language we highly encourage you to [contribute translation files](https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md) for the missing language.
|
||||
|
||||
## Restrict Languages
|
||||
|
||||
If you only want to enable a subset of the supported languages, you can configure the languages you'd like to allow using the [restrictions API](./restrictions.md).
|
||||
The login UI and notification messages are only rendered in one of the allowed languages and fallback to the instances default language.
|
||||
Also, the instances OIDC discovery endpoint will only list the allowed languages in the *ui_locales_supported* field.
|
||||
|
||||
All language settings are also configurable in the consoles *Languages* instance settings.
|
||||
|
||||

|
||||
|
BIN
docs/static/img/guides/console/languages.png
vendored
Normal file
BIN
docs/static/img/guides/console/languages.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 128 KiB |
Loading…
x
Reference in New Issue
Block a user