error management

This commit is contained in:
2024-10-27 20:06:51 +01:00
parent 19177eefdf
commit f404ad3088
14 changed files with 93 additions and 72 deletions
@@ -28,6 +28,7 @@ public class PasswordModelValidator implements Validator {
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_WHITESPACE = "password.rule.whitespace"; public static final String SYSTEM_PROPERTY_PASSWORD_RULE_WHITESPACE = "password.rule.whitespace";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_LENGTH = "password.rule.length"; public static final String SYSTEM_PROPERTY_PASSWORD_RULE_LENGTH = "password.rule.length";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_LOWERCASE = "password.rule.lowercase";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_UPPERCASE = "password.rule.uppercase"; public static final String SYSTEM_PROPERTY_PASSWORD_RULE_UPPERCASE = "password.rule.uppercase";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_DIGIT = "password.rule.digit"; public static final String SYSTEM_PROPERTY_PASSWORD_RULE_DIGIT = "password.rule.digit";
public static final String SYSTEM_PROPERTY_PASSWORD_RULE_SPECIAL = "password.rule.special"; public static final String SYSTEM_PROPERTY_PASSWORD_RULE_SPECIAL = "password.rule.special";
@@ -52,6 +53,11 @@ public class PasswordModelValidator implements Validator {
rules.add(new LengthRule(length, 4096)); rules.add(new LengthRule(length, 4096));
} }
int lowercase = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_LOWERCASE, 1);
if (lowercase > 0) {
rules.add(new CharacterRule(EnglishCharacterData.LowerCase, lowercase));
}
int uppercase = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_UPPERCASE, 1); int uppercase = systemPropertyManager.getInteger(SYSTEM_PROPERTY_PASSWORD_RULE_UPPERCASE, 1);
if (uppercase > 0) { if (uppercase > 0) {
rules.add(new CharacterRule(EnglishCharacterData.UpperCase, uppercase)); rules.add(new CharacterRule(EnglishCharacterData.UpperCase, uppercase));
@@ -73,7 +79,7 @@ public class PasswordModelValidator implements Validator {
if (!result.isValid()) { if (!result.isValid()) {
for (RuleResultDetail ruleResultDetail : result.getDetails()) { for (RuleResultDetail ruleResultDetail : result.getDetails()) {
errors.rejectValue("password", ruleResultDetail.getErrorCode()); errors.rejectValue("password", ruleResultDetail.getErrorCode(), ruleResultDetail.getValues(), null);
} }
} }
@@ -32,11 +32,11 @@ public class TurnoverValidator implements Validator {
} }
if (turnover.getPrice() < 0) { if (turnover.getPrice() < 0) {
errors.rejectValue("price", "POSITIVE_VALUE"); errors.rejectValue("price", "MIN");
} }
if (turnover.getGiftcardPrice() != null && turnover.getGiftcardPrice() < 0) { if (turnover.getGiftcardPrice() != null && turnover.getGiftcardPrice() < 0) {
errors.rejectValue("giftcardPrice", "POSITIVE_VALUE"); errors.rejectValue("giftcardPrice", "MIN");
} else if (turnover.getGiftcardPrice() != null && turnover.getGiftcardPrice() > turnover.getPrice()) { } else if (turnover.getGiftcardPrice() != null && turnover.getGiftcardPrice() > turnover.getPrice()) {
errors.rejectValue("giftcardPrice", "GREATER_THAN_PRICE"); errors.rejectValue("giftcardPrice", "GREATER_THAN_PRICE");
} }
+10 -9
View File
@@ -19,7 +19,7 @@ import { PageNotFound } from './pages/notfound/notfound.page';
import { PageProfile } from './pages/profile/profile.page'; import { PageProfile } from './pages/profile/profile.page';
import { PageUnavailable } from './pages/unavailable/unavailable.page'; import { PageUnavailable } from './pages/unavailable/unavailable.page';
import { UiMain } from './ui/main/main.ui'; import { UiMain } from './ui/main/main.ui';
import { I18nEmptyPipe, I18nPipe } from './utils/i18n.pipe'; import { ErrorCodePipe, I18nEmptyPipe, I18nPipe } from './utils/i18n.pipe';
import { MomentPipe } from './utils/moment.pipe'; import { MomentPipe } from './utils/moment.pipe';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field'; import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
@@ -66,32 +66,33 @@ export class XhrInterceptor implements HttpInterceptor {
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent,
AutofocusDirective, AutofocusDirective,
ConfirmDialog,
ErrorCodePipe,
I18nPipe, I18nPipe,
I18nEmptyPipe, I18nEmptyPipe,
MomentPipe, MomentPipe,
AppComponent,
PageTurnovers,
PageTurnoversManage,
PageTurnover,
PageLogin, PageLogin,
PageManagement, PageManagement,
PageNotFound, PageNotFound,
PagePassword, PagePassword,
PageProfile, PageProfile,
PageTurnover,
PageTurnovers,
PageTurnoversManage,
PageUnavailable, PageUnavailable,
PageUsers, PageUsers,
PageUserCreate, PageUserCreate,
UiMain, UiMain,
UiTurnovers, UiTurnovers
ConfirmDialog
], ],
imports: [ imports: [
BrowserModule,
AppRoutingModule, AppRoutingModule,
BrowserModule,
BrowserAnimationsModule, BrowserAnimationsModule,
MaterialModule,
FormsModule, FormsModule,
MaterialModule,
ReactiveFormsModule, ReactiveFormsModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production, registrationStrategy: 'registerWhenStable:30000' }), ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production, registrationStrategy: 'registerWhenStable:30000' }),
], ],
@@ -7,21 +7,21 @@
<mat-label>{{'password.old' | i18n}}</mat-label> <mat-label>{{'password.old' | i18n}}</mat-label>
<input matInput formControlName="old" type="password"> <input matInput formControlName="old" type="password">
<mat-error *ngFor="let error of passwordForm.get('old').errors | keyvalue"> <mat-error *ngFor="let error of passwordForm.get('old').errors | keyvalue">
{{'password.error.' + error.key | i18n}} {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field> <mat-form-field>
<mat-label>{{'password.new' | i18n}}</mat-label> <mat-label>{{'password.new' | i18n}}</mat-label>
<input matInput formControlName="password" type="password"> <input matInput formControlName="password" type="password">
<mat-error *ngFor="let error of passwordForm.get('password').errors | keyvalue"> <mat-error *ngFor="let error of passwordForm.get('password').errors | keyvalue">
{{'password.error.' + error.key | i18n}} {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field> <mat-form-field>
<mat-label>{{'password.repeat' | i18n}}</mat-label> <mat-label>{{'password.repeat' | i18n}}</mat-label>
<input matInput formControlName="password2" type="password"> <input matInput formControlName="password2" type="password">
<mat-error *ngFor="let error of passwordForm.get('password2').errors | keyvalue"> <mat-error *ngFor="let error of passwordForm.get('password2').errors | keyvalue">
{{'password.error.' + error.key | i18n}} {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</mat-card-content> </mat-card-content>
@@ -53,9 +53,9 @@ export class PagePassword implements OnInit, OnDestroy {
this.working = false; this.working = false;
if (error.status == 409) { if (error.status == 409) {
let errors = {}; let errors = {};
for (let code of error.error) { for (let errorObject of error.error) {
errors[code.field] = errors[code.field] || {}; errors[errorObject.field] = errors[errorObject.field] || {};
errors[code.field][code.code] = true; errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
} }
for (let code in errors) { for (let code in errors) {
@@ -50,14 +50,14 @@
<mat-label>{{'password.new' | i18n}}</mat-label> <mat-label>{{'password.new' | i18n}}</mat-label>
<input matInput formControlName="password" type="password"> <input matInput formControlName="password" type="password">
<mat-error *ngFor="let error of passwordForm.get('password').errors | keyvalue"> <mat-error *ngFor="let error of passwordForm.get('password').errors | keyvalue">
{{'password.error.' + error.key | i18n}} {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field> <mat-form-field>
<mat-label>{{'password.repeat' | i18n}}</mat-label> <mat-label>{{'password.repeat' | i18n}}</mat-label>
<input matInput formControlName="password2" type="password"> <input matInput formControlName="password2" type="password">
<mat-error *ngFor="let error of passwordForm.get('password2').errors | keyvalue"> <mat-error *ngFor="let error of passwordForm.get('password2').errors | keyvalue">
{{'password.error.' + error.key | i18n}} {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</mat-card-content> </mat-card-content>
@@ -108,10 +108,10 @@ export class PageProfile implements OnInit, OnDestroy {
this.working = false; this.working = false;
if (error.status == 422) { if (error.status == 422) {
let errors = {}; let errors = {};
for (let code of error.error) { for (let errorObject of error.error) {
errors[code.field] = errors[code.field] || {}; errors[errorObject.field] = errors[errorObject.field] || {};
errors[code.field][code.code] = true; errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
} }
for (let code in errors) { for (let code in errors) {
this.profileForm.get(code).setErrors(errors[code]); this.profileForm.get(code).setErrors(errors[code]);
@@ -138,10 +138,10 @@ export class PageProfile implements OnInit, OnDestroy {
this.working = false; this.working = false;
if (error.status == 409) { if (error.status == 409) {
let errors = {}; let errors = {};
for (let code of error.error) { for (let errorObject of error.error) {
errors[code.field] = errors[code.field] || {}; errors[errorObject.field] = errors[errorObject.field] || {};
errors[code.field][code.code] = true; errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
} }
for (let code in errors) { for (let code in errors) {
this.passwordForm.get(code).setErrors(errors[code]); this.passwordForm.get(code).setErrors(errors[code]);
@@ -25,7 +25,7 @@
<mat-label>{{'turnover.customer' | i18n}}</mat-label> <mat-label>{{'turnover.customer' | i18n}}</mat-label>
<input matInput formControlName="customer" type="text" [required]="true"> <input matInput formControlName="customer" type="text" [required]="true">
<mat-error *ngFor="let error of form.get('customer').errors | keyvalue"> <mat-error *ngFor="let error of form.get('customer').errors | keyvalue">
{{'turnover.customer.error.' + error.key | i18n}} {{'turnover.customer.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -33,7 +33,7 @@
<mat-label>{{'turnover.motif' | i18n}}</mat-label> <mat-label>{{'turnover.motif' | i18n}}</mat-label>
<input matInput formControlName="motif" type="text" [required]="true"> <input matInput formControlName="motif" type="text" [required]="true">
<mat-error *ngFor="let error of form.get('motif').errors | keyvalue"> <mat-error *ngFor="let error of form.get('motif').errors | keyvalue">
{{'turnover.motif.error.' + error.key | i18n}} {{'turnover.motif.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -42,7 +42,7 @@
<input matInput formControlName="price" type="number" min="0" step="0.01" [required]="true"> <input matInput formControlName="price" type="number" min="0" step="0.01" [required]="true">
<span matTextSuffix>{{'turnover.price.suffix' | i18n}}</span> <span matTextSuffix>{{'turnover.price.suffix' | i18n}}</span>
<mat-error *ngFor="let error of form.get('price').errors | keyvalue"> <mat-error *ngFor="let error of form.get('price').errors | keyvalue">
{{'turnover.price.error.' + error.key | i18n}} {{'turnover.price.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -54,7 +54,7 @@
<mat-label>{{'turnover.giftcard.number' | i18n}}</mat-label> <mat-label>{{'turnover.giftcard.number' | i18n}}</mat-label>
<input matInput formControlName="giftcardNumber" type="text"> <input matInput formControlName="giftcardNumber" type="text">
<mat-error *ngFor="let error of form.get('giftcardNumber').errors | keyvalue"> <mat-error *ngFor="let error of form.get('giftcardNumber').errors | keyvalue">
{{'turnover.giftcard.number.error.' + error.key | i18n}} {{'turnover.giftcard.number.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -63,7 +63,7 @@
<input matInput formControlName="giftcardPrice" type="number" min="0" step="0.01"> <input matInput formControlName="giftcardPrice" type="number" min="0" step="0.01">
<span matTextSuffix>{{'turnover.price.suffix' | i18n}}</span> <span matTextSuffix>{{'turnover.price.suffix' | i18n}}</span>
<mat-error *ngFor="let error of form.get('giftcardPrice').errors | keyvalue"> <mat-error *ngFor="let error of form.get('giftcardPrice').errors | keyvalue">
{{'turnover.giftcard.price.error.' + error.key | i18n}} {{'turnover.giftcard.price.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -72,7 +72,7 @@
<input matInput formControlName="timeInvestment" type="number" min="0" step="0.1"> <input matInput formControlName="timeInvestment" type="number" min="0" step="0.1">
<span matTextSuffix>{{'turnover.timeInvestment.suffix' | i18n}}</span> <span matTextSuffix>{{'turnover.timeInvestment.suffix' | i18n}}</span>
<mat-error *ngFor="let error of form.get('timeInvestment').errors | keyvalue"> <mat-error *ngFor="let error of form.get('timeInvestment').errors | keyvalue">
{{'turnover.timeInvestment.error.' + error.key | i18n}} {{'turnover.timeInvestment.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -80,7 +80,7 @@
<mat-label>{{'turnover.remark' | i18n}}</mat-label> <mat-label>{{'turnover.remark' | i18n}}</mat-label>
<textarea matAutosize matAutosizeMinRows="3" matInput formControlName="remark"></textarea> <textarea matAutosize matAutosizeMinRows="3" matInput formControlName="remark"></textarea>
<mat-error *ngFor="let error of form.get('remark').errors | keyvalue"> <mat-error *ngFor="let error of form.get('remark').errors | keyvalue">
{{'turnover.remark.error.' + error.key | i18n}} {{'turnover.remark.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -88,7 +88,7 @@
<mat-label>{{'turnover.materialConsumption' | i18n}}</mat-label> <mat-label>{{'turnover.materialConsumption' | i18n}}</mat-label>
<textarea matAutosize matAutosizeMinRows="3" matInput formControlName="materialConsumption"></textarea> <textarea matAutosize matAutosizeMinRows="3" matInput formControlName="materialConsumption"></textarea>
<mat-error *ngFor="let error of form.get('materialConsumption').errors | keyvalue"> <mat-error *ngFor="let error of form.get('materialConsumption').errors | keyvalue">
{{'turnover.materialConsumption.error.' + error.key | i18n}} {{'turnover.materialConsumption.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -137,10 +137,10 @@ export class PageTurnover implements OnInit {
this.working = false; this.working = false;
if (error.status == 422) { if (error.status == 422) {
let errors = {}; let errors = {};
for (let code of error.error) { for (let errorObject of error.error) {
errors[code.field] = errors[code.field] || {}; errors[errorObject.field] = errors[errorObject.field] || {};
errors[code.field][code.code] = true; errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
} }
for (let code in errors) { for (let code in errors) {
this.form.get(code).setErrors(errors[code]); this.form.get(code).setErrors(errors[code]);
@@ -188,10 +188,10 @@ export class PageTurnover implements OnInit {
} }
if (error.status == 409) { if (error.status == 409) {
let errors = {}; let errors = {};
for (let code of error.error) { for (let errorObject of error.error) {
errors[code.field] = errors[code.field] || {}; errors[errorObject.field] = errors[errorObject.field] || {};
errors[code.field][code.code] = true; errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
} }
for (let code in errors) { for (let code in errors) {
this.form.get(code).setErrors(errors[code]); this.form.get(code).setErrors(errors[code]);
@@ -6,7 +6,7 @@
<mat-label>{{'profile.username' | i18n}}</mat-label> <mat-label>{{'profile.username' | i18n}}</mat-label>
<input matInput formControlName="username" type="text" [required]="true"> <input matInput formControlName="username" type="text" [required]="true">
<mat-error *ngFor="let error of form.get('username').errors | keyvalue"> <mat-error *ngFor="let error of form.get('username').errors | keyvalue">
{{'user.error.' + error.key | i18n}} {{'user.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -14,7 +14,7 @@
<mat-label>{{'profile.name' | i18n}}</mat-label> <mat-label>{{'profile.name' | i18n}}</mat-label>
<input matInput formControlName="name" type="text"> <input matInput formControlName="name" type="text">
<mat-error *ngFor="let error of form.get('name').errors | keyvalue"> <mat-error *ngFor="let error of form.get('name').errors | keyvalue">
{{'user.error.' + error.key | i18n}} {{'user.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -22,7 +22,7 @@
<mat-label>{{'profile.email' | i18n}}</mat-label> <mat-label>{{'profile.email' | i18n}}</mat-label>
<input matInput formControlName="email" type="email"> <input matInput formControlName="email" type="email">
<mat-error *ngFor="let error of form.get('email').errors | keyvalue"> <mat-error *ngFor="let error of form.get('email').errors | keyvalue">
{{'user.error.' + error.key | i18n}} {{'user.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -30,7 +30,7 @@
<mat-label>{{'user.password' | i18n}}</mat-label> <mat-label>{{'user.password' | i18n}}</mat-label>
<input matInput formControlName="password" type="password"> <input matInput formControlName="password" type="password">
<mat-error *ngFor="let error of form.get('password').errors | keyvalue"> <mat-error *ngFor="let error of form.get('password').errors | keyvalue">
{{'password.error.' + error.key | i18n}} {{'password.error.' + (error.key | errorCode) | i18n:error.value}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -52,12 +52,13 @@ export class PageUserCreate implements OnInit {
this.working = false; this.working = false;
if (error.status == 409) { if (error.status == 409) {
let errors = {}; let errors = {};
for (let code of error.error) { for (let errorObject of error.error) {
errors[code.field] = errors[code.field] || {}; errors[errorObject.field] = errors[errorObject.field] || {};
errors[code.field][code.code] = true; errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
} }
for (let code in errors) { for (let code in errors) {
console.log(code, errors[code]);
this.form.get(code).setErrors(errors[code]); this.form.get(code).setErrors(errors[code]);
} }
} }
@@ -68,9 +69,9 @@ export class PageUserCreate implements OnInit {
this.working = false; this.working = false;
if (error.status == 409) { if (error.status == 409) {
let errors = {}; let errors = {};
for (let code of error.error) { for (let errorObject of error.error) {
errors[code.field] = errors[code.field] || {}; errors[errorObject.field] = errors[errorObject.field] || {};
errors[code.field][code.code] = true; errors[errorObject.field][errorObject.code] = errorObject.arguments || true;
} }
for (let code in errors) { for (let code in errors) {
+2 -2
View File
@@ -22,8 +22,8 @@ export class UiMain {
opened: boolean = true; opened: boolean = true;
darkTheme: boolean = false; darkTheme: boolean = false;
title = 'buntspecht'; title = 'buntspecht';
currentLocale: String; currentLocale: string;
datetimeformat: String; datetimeformat: string;
locales; locales;
authenticated: boolean = false; authenticated: boolean = false;
username: string = ""; username: string = "";
+15 -2
View File
@@ -12,7 +12,10 @@ export class I18nPipe implements PipeTransform {
constructor(private i18n: I18nService) { constructor(private i18n: I18nService) {
} }
transform(value: String, ...args: any[]): String { transform(value: string, ...args: any[]): string {
if (args.length === 1 && Array.isArray(args[0])) {
args = args[0];
}
return this.i18n.get(value, args); return this.i18n.get(value, args);
} }
} }
@@ -25,7 +28,17 @@ export class I18nEmptyPipe implements PipeTransform {
constructor(private i18n: I18nService) { constructor(private i18n: I18nService) {
} }
transform(value: String, ...args: any[]): String { transform(value: string, ...args: any[]): string {
return this.i18n.getEmpty(value, args); return this.i18n.getEmpty(value, args);
} }
}
@Pipe({
name: 'errorCode'
})
export class ErrorCodePipe implements PipeTransform {
transform(value: string): string {
return value && value.toUpperCase().replaceAll('-', '_') || value;
}
} }
+14 -14
View File
@@ -63,12 +63,12 @@
".": "Passwort ändern", ".": "Passwort ändern",
"error": { "error": {
"ILLEGAL_WHITESPACE": "Bitte keine Leerzeichen verwenden.", "ILLEGAL_WHITESPACE": "Bitte keine Leerzeichen verwenden.",
"INSUFFICIENT_DIGIT": "Bitte mindestens eine Zahl eingeben.", "INSUFFICIENT_DIGIT": "Bitte mindestens {0} Zahl/en eingeben.",
"INSUFFICIENT_LOWERCASE": "Bitte mindestens einen Kleinbuchstaben eingeben.", "INSUFFICIENT_LOWERCASE": "Bitte mindestens {0} Kleinbuchstaben eingeben.",
"INSUFFICIENT_SPECIAL": "Bitte mindestens ein Sonderzeichen eingeben.", "INSUFFICIENT_SPECIAL": "Bitte mindestens {0} Sonderzeichen eingeben.",
"INSUFFICIENT_UPPERCASE": "Bitte mindestens einen Großbuchstaben eingeben.", "INSUFFICIENT_UPPERCASE": "Bitte mindestens {0} Großbuchstaben eingeben.",
"NOT_MATCH": "Passwörter stimmen nicht überein.", "NOT_MATCH": "Passwörter stimmen nicht überein.",
"TOO_SHORT": "Bitte ein längeres Passwort wählen.", "TOO_SHORT": "Bitte Mindestens {0} Zeichen verwenden.",
"UNAUTHORIZED": "Falsches Passwort" "UNAUTHORIZED": "Falsches Passwort"
}, },
"old": "Altes Password", "old": "Altes Password",
@@ -108,7 +108,7 @@
"customer": { "customer": {
".": "Kunde", ".": "Kunde",
"error": { "error": {
"required": "Angabe von Kunde erforderlich" "REQUIRED": "Angabe von Kunde erforderlich"
} }
}, },
"dueDate": { "dueDate": {
@@ -122,14 +122,13 @@
"giftcard": { "giftcard": {
".": "Gutschein", ".": "Gutschein",
"number": { "number": {
".": "Gutscheinnummer", ".": "Gutscheinnummer"
"error": ""
}, },
"price": { "price": {
".": "Gutscheinwert", ".": "Gutscheinwert",
"error": { "error": {
"GREATER_THAN_PRICE": "Gutscheinwert übersteigt Preis", "GREATER_THAN_PRICE": "Gutscheinwert übersteigt Preis",
"min": "Üngültiger Wert" "MIN": "Üngültiger Wert"
} }
}, },
"priceUsage": "Gutscheinanteil" "priceUsage": "Gutscheinanteil"
@@ -139,14 +138,14 @@
"motif": { "motif": {
".": "Motiv", ".": "Motiv",
"error": { "error": {
"required": "Angabe von Motiv erforderlich" "REQUIRED": "Angabe von Motiv erforderlich"
} }
}, },
"price": { "price": {
".": "Preis", ".": "Preis",
"error": { "error": {
"min": "Üngültiger Wert", "MIN": "Üngültiger Wert",
"required": "Angabe des Preises erforderlich" "REQUIRED": "Angabe des Preises erforderlich"
}, },
"suffix": "€", "suffix": "€",
"total": "Umsatz: {0} €" "total": "Umsatz: {0} €"
@@ -156,7 +155,7 @@
"timeInvestment": { "timeInvestment": {
".": "Zeiteinsatz", ".": "Zeiteinsatz",
"error": { "error": {
"min": "Üngültiger Wert" "MIN": "Üngültiger Wert"
}, },
"suffix": "Std.", "suffix": "Std.",
"total": "Zeiteinsatz: {0} Std." "total": "Zeiteinsatz: {0} Std."
@@ -199,7 +198,8 @@
"create": "Neuen User erstellen", "create": "Neuen User erstellen",
"delete": "User löschen", "delete": "User löschen",
"error": { "error": {
"ALREADY_EXISTS": "User existiert bereits" "ALREADY_EXISTS": "User existiert bereits",
"REQUIRED": "Angabe eines Usernames erforderlich"
}, },
"manage": "Verwalten", "manage": "Verwalten",
"password": "Passwort", "password": "Passwort",