diff --git a/.gitignore b/.gitignore index a920879bb..7bfea35e2 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ version.properties paligo-styles/style.css* migrations.json +*.iml diff --git a/angular.json b/angular.json index 74f43eddd..e025a6a56 100644 --- a/angular.json +++ b/angular.json @@ -1,4 +1,7 @@ { + "cli": { + "analytics": "d22ff5ae-c863-4253-83e3-0a969e4bb5fe" + }, "version": 1, "projects": { "common-ui": { diff --git a/apps/red-ui/src/app/i18n/language.service.ts b/apps/red-ui/src/app/i18n/language.service.ts index 4f4331ae7..906ac365b 100644 --- a/apps/red-ui/src/app/i18n/language.service.ts +++ b/apps/red-ui/src/app/i18n/language.service.ts @@ -25,6 +25,7 @@ export class LanguageService { } else { defaultLang = 'en'; } + console.log(defaultLang); document.documentElement.lang = defaultLang; this._translateService.setDefaultLang(defaultLang); this._translateService.use(defaultLang).toPromise().then(); diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html index a056d7d3c..ea0944da4 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html @@ -7,16 +7,16 @@
-
{{ dictionary?.type || technicalName || '-' }}
+
{{ dictionary?.type || (technicalName$ | async) || '-' }}
-
+
{{ dictionary.label }}
-
+
- +
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts index 6fe2d7c2e..75fe1ac4e 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts @@ -1,39 +1,47 @@ -import { Component, Inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Observable } from 'rxjs'; -import { BaseDialogComponent, Toaster } from '@iqser/common-ui'; +import { BaseDialogComponent, shareDistinctLast, Toaster } from '@iqser/common-ui'; import { TranslateService } from '@ngx-translate/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { AppStateService } from '@state/app-state.service'; import { toKebabCase } from '@utils/functions'; import { DictionaryService } from '@shared/services/dictionary.service'; import { Dictionary, IDictionary } from '@red/domain'; +import { UserService } from '@services/user.service'; +import { map } from 'rxjs/operators'; @Component({ selector: 'redaction-add-edit-dictionary-dialog', templateUrl: './add-edit-dictionary-dialog.component.html', styleUrls: ['./add-edit-dictionary-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class AddEditDictionaryDialogComponent extends BaseDialogComponent { - form: FormGroup; - readonly dictionary: Dictionary; - technicalName = ''; - private readonly _dossierTemplateId: string; + readonly form: FormGroup; + readonly dictionary = this._data.dictionary; + readonly canEditLabel$ = this._canEditLabel$; + readonly technicalName$: Observable; + readonly dialogHeader = this._translateService.instant('add-edit-dictionary.title', { + type: this._data.dictionary ? 'edit' : 'create', + name: this._data.dictionary?.label, + }); + readonly hasColor$: Observable; + private readonly _dossierTemplateId = this._data.dossierTemplateId; constructor( - private readonly _dictionaryService: DictionaryService, - private readonly _appStateService: AppStateService, - private readonly _formBuilder: FormBuilder, + readonly userService: UserService, private readonly _toaster: Toaster, + private readonly _formBuilder: FormBuilder, + private readonly _appStateService: AppStateService, private readonly _translateService: TranslateService, + private readonly _dictionaryService: DictionaryService, private readonly _dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) - private readonly _data: { dictionary: Dictionary; dossierTemplateId: string }, + private readonly _data: { readonly dictionary: Dictionary; readonly dossierTemplateId: string }, ) { super(); - this.dictionary = _data.dictionary; - this._dossierTemplateId = _data.dossierTemplateId; this.form = _formBuilder.group({ label: [this.dictionary?.label, [Validators.required, Validators.minLength(3)]], description: [this.dictionary?.description], @@ -43,21 +51,8 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent { addToDictionaryAction: [!!this.dictionary?.addToDictionaryAction], caseSensitive: [this.dictCaseSensitive], }); - this.form.get('label').valueChanges.subscribe(() => { - this._updateTechnicalName(); - }); - } - - get dialogHeader(): string { - return this._translateService.instant('add-edit-dictionary.title', { - type: this.dictionary ? 'edit' : 'create', - name: this.dictionary?.label, - }); - } - - get hasColor(): boolean { - const hexColorValue = this.form.get('hexColor').value; - return !hexColorValue || hexColorValue?.length === 0; + this.hasColor$ = this._colorEmpty$; + this.technicalName$ = this.form.get('label').valueChanges.pipe(map(value => this._toTechnicalName(value))); } get dictCaseSensitive(): boolean { @@ -82,21 +77,34 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent { return false; } - save(): void { + private get _canEditLabel$() { + return this.userService.currentUser$.pipe( + map(user => user.isAdmin || !this._data.dictionary), + shareDistinctLast(), + ); + } + + private get _colorEmpty$() { + return this.form.get('hexColor').valueChanges.pipe(map((value: string) => !value || value?.length === 0)); + } + + async save(): Promise { const dictionary = this._formToObject(); let observable: Observable; + const dossierTemplateId = this._data.dossierTemplateId; if (this.dictionary) { // edit mode - observable = this._dictionaryService.updateDictionary(dictionary, this._dossierTemplateId, dictionary.type); + observable = this._dictionaryService.updateDictionary(dictionary, dossierTemplateId, dictionary.type); } else { // create mode - observable = this._dictionaryService.addDictionary({ ...dictionary, dossierTemplateId: this._dossierTemplateId }); + observable = this._dictionaryService.addDictionary({ ...dictionary, dossierTemplateId }); } - observable.subscribe( - () => this._dialogRef.close(true), - error => { + return observable + .toPromise() + .then(() => this._dialogRef.close(true)) + .catch(error => { if (error.status === 409) { this._toaster.error(_('add-edit-dictionary.error.dictionary-already-exists')); } else if (error.status === 400) { @@ -104,25 +112,23 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent { } else { this._toaster.error(_('add-edit-dictionary.error.generic')); } - }, - ); + }); } - private _updateTechnicalName() { - const displayName = this.form.get('label').value.trim(); + private _toTechnicalName(value: string) { const existingTechnicalNames = Object.keys(this._appStateService.dictionaryData[this._dossierTemplateId]); - const baseTechnicalName: string = toKebabCase(displayName); + const baseTechnicalName = toKebabCase(value.trim()); let technicalName = baseTechnicalName; let suffix = 1; while (existingTechnicalNames.includes(technicalName)) { technicalName = [baseTechnicalName, suffix++].join('-'); } - this.technicalName = technicalName; + return technicalName; } private _formToObject(): IDictionary { return { - type: this.dictionary?.type || this.technicalName, + type: this.dictionary?.type || this._toTechnicalName(this.form.get('label').value), label: this.form.get('label').value, caseInsensitive: !this.form.get('caseSensitive').value, description: this.form.get('description').value, @@ -130,7 +136,7 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent { hint: this.form.get('hint').value, rank: this.form.get('rank').value, addToDictionaryAction: this.form.get('addToDictionaryAction').value, - dossierTemplateId: this._dossierTemplateId, + dossierTemplateId: this._data.dossierTemplateId, }; } } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts index 1a0df33c3..bc5317096 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts @@ -1,9 +1,8 @@ import { Component, EventEmitter, forwardRef, Injector, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; -import { Field } from '../file-attributes-csv-import-dialog.component'; import { CircleButtonTypes, DefaultListingServices, ListingComponent, TableColumnConfig } from '@iqser/common-ui'; import { fileAttributeTypesTranslations } from '../../../translations/file-attribute-types-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { FileAttributeConfigTypes } from '@red/domain'; +import { FileAttributeConfigTypes, IField } from '@red/domain'; @Component({ selector: 'redaction-active-fields-listing', @@ -11,11 +10,11 @@ import { FileAttributeConfigTypes } from '@red/domain'; styleUrls: ['./active-fields-listing.component.scss'], providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => ActiveFieldsListingComponent) }], }) -export class ActiveFieldsListingComponent extends ListingComponent implements OnChanges { +export class ActiveFieldsListingComponent extends ListingComponent implements OnChanges { readonly circleButtonTypes = CircleButtonTypes; readonly translations = fileAttributeTypesTranslations; readonly tableHeaderLabel = _('file-attributes-csv-import.table-header.title'); - readonly tableColumnConfigs: TableColumnConfig[] = [ + readonly tableColumnConfigs: TableColumnConfig[] = [ { label: _('file-attributes-csv-import.table-col-names.name'), class: 'name', @@ -40,10 +39,10 @@ export class ActiveFieldsListingComponent extends ListingComponent implem }, ]; readonly typeOptions = Object.keys(FileAttributeConfigTypes); - @Input() entities: Field[]; - @Output() readonly entitiesChange = new EventEmitter(); + @Input() entities: IField[]; + @Output() readonly entitiesChange = new EventEmitter(); @Output() readonly setHoveredColumn = new EventEmitter(); - @Output() readonly toggleFieldActive = new EventEmitter(); + @Output() readonly toggleFieldActive = new EventEmitter(); constructor(protected readonly _injector: Injector) { super(_injector); @@ -68,7 +67,7 @@ export class ActiveFieldsListingComponent extends ListingComponent implem } } - togglePrimary(field: Field) { + togglePrimary(field: IField) { if (field.primaryAttribute) { field.primaryAttribute = false; return; @@ -80,6 +79,6 @@ export class ActiveFieldsListingComponent extends ListingComponent implem field.primaryAttribute = true; } - itemMouseEnterFn = (field: Field) => this.setHoveredColumn.emit(field.csvColumn); + itemMouseEnterFn = (field: IField) => this.setHoveredColumn.emit(field.csvColumn); itemMouseLeaveFn = () => this.setHoveredColumn.emit(); } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts index e0d094671..349cd8c55 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts @@ -1,33 +1,25 @@ -import { Component, Inject, Injector } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core'; import { AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import * as Papa from 'papaparse'; import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; -import { DefaultListingServices, IListable, ListingComponent, TableColumnConfig, Toaster } from '@iqser/common-ui'; +import { DefaultListingServices, ListingComponent, TableColumnConfig, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { FileAttributeConfig, FileAttributeConfigType, FileAttributeConfigTypes, IFileAttributesConfig } from '@red/domain'; +import { FileAttributeConfig, FileAttributeConfigTypes, IField, IFileAttributesConfig } from '@red/domain'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; -export interface Field extends IListable { - id: string; - csvColumn: string; - name: string; - type: FileAttributeConfigType; - readonly: boolean; - primaryAttribute: boolean; -} - @Component({ templateUrl: './file-attributes-csv-import-dialog.component.html', styleUrls: ['./file-attributes-csv-import-dialog.component.scss'], providers: [...DefaultListingServices], + changeDetection: ChangeDetectionStrategy.OnPush, }) -export class FileAttributesCsvImportDialogComponent extends ListingComponent { - readonly tableColumnConfigs: TableColumnConfig[] = []; - parseResult: { data: any[]; errors: any[]; meta: any; fields: Field[] }; +export class FileAttributesCsvImportDialogComponent extends ListingComponent { + readonly tableColumnConfigs: TableColumnConfig[] = []; + parseResult: { data: any[]; errors: any[]; meta: any; fields: IField[] }; hoveredColumn: string; - activeFields: Field[] = []; + activeFields: IField[] = []; readonly baseConfigForm: FormGroup; isSearchOpen = false; previewExpanded = true; @@ -62,6 +54,7 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent a.csvColumnHeader === entity.csvColumn); + const existing = this.data.existingConfiguration.fileAttributeConfigs?.find(a => a.csvColumnHeader === entity.csvColumn); if (existing) { entity.id = existing.id; entity.name = existing.label; @@ -142,11 +135,11 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent f.id === field.id); } - toggleFieldActive(field: Field) { + toggleFieldActive(field: IField) { if (!this.isActive(field)) { this.activeFields = [...this.activeFields, { ...field, searchKey: field.csvColumn }]; } else { @@ -219,7 +212,7 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent {{ term }}. {{ 'search-screen.must-contain' | translate }}: -  {{ term }} diff --git a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.ts index 7f63f7a04..c409a94dc 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.ts @@ -1,7 +1,6 @@ -import { Component, forwardRef, Injector, OnDestroy } from '@angular/core'; +import { ChangeDetectionStrategy, Component, forwardRef, Injector, OnDestroy } from '@angular/core'; import { DefaultListingServices, - IListable, keyChecker, List, ListingComponent, @@ -10,8 +9,8 @@ import { SearchPositions, TableColumnConfig, } from '@iqser/common-ui'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { debounceTime, map, skip, switchMap, tap } from 'rxjs/operators'; +import { merge, Observable } from 'rxjs'; +import { debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators'; import { ActivatedRoute, Router } from '@angular/router'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { fileStatusTranslations } from '../../translations/file-status-translations'; @@ -19,44 +18,38 @@ import { TranslateService } from '@ngx-translate/core'; import { RouterHistoryService } from '@services/router-history.service'; import { DossiersService } from '@services/entity-services/dossiers.service'; import { PlatformSearchService } from '../../shared/services/platform-search.service'; -import { IMatchedDocument, ISearchResponse } from '@red/domain'; +import { IMatchedDocument, ISearchInput, ISearchListItem, ISearchResponse } from '@red/domain'; -interface ListItem extends IListable { - readonly dossierId: string; - readonly filename: string; - readonly unmatched: List | null; - readonly highlights: Record; - readonly routerLink: string; - readonly status: string; - readonly dossierName: string; - readonly numberOfPages: number; -} - -interface SearchInput { - readonly query: string; - readonly dossierIds?: List; +function toSearchInput(query: string, dossierIds: List | string): ISearchInput { + return { + query, + dossierIds: dossierIds ? (typeof dossierIds === 'string' ? [dossierIds] : dossierIds) : [], + }; } @Component({ templateUrl: './search-screen.component.html', styleUrls: ['./search-screen.component.scss'], providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => SearchScreenComponent) }], + changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SearchScreenComponent extends ListingComponent implements OnDestroy { +export class SearchScreenComponent extends ListingComponent implements OnDestroy { readonly fileStatusTranslations = fileStatusTranslations; readonly searchPositions = SearchPositions; readonly tableHeaderLabel = _('search-screen.table-header'); - readonly tableColumnConfigs: TableColumnConfig[] = [ + readonly tableColumnConfigs: TableColumnConfig[] = [ { label: _('search-screen.cols.document'), width: '2fr' }, { label: _('search-screen.cols.status') }, { label: _('search-screen.cols.dossier') }, { label: _('search-screen.cols.pages'), width: 'auto' }, ]; - readonly search$ = new BehaviorSubject(null); - readonly searchResults$: Observable = this.search$.asObservable().pipe( + + readonly searchResults$ = merge(this._searchChanged$, this._filtersChanged$).pipe( + startWith(this._routeQuery), tap(() => this._loadingService.start()), - switchMap(query => this._search(query)), + tap(value => this.updateNavigation(value.query)), + switchMap(query => this._platformSearchService.search(query)), map(searchResult => this._toMatchedDocuments(searchResult)), map(docs => this._toListItems(docs)), tap(result => this.entitiesService.setEntities(result)), @@ -76,6 +69,7 @@ export class SearchScreenComponent extends ListingComponent implements super(_injector); this.searchService.skip = true; + const dossierId = _activatedRoute.snapshot.queryParamMap.get('dossierId'); this.filterService.addFilterGroups([ { slug: 'dossiers', @@ -87,57 +81,53 @@ export class SearchScreenComponent extends ListingComponent implements new NestedFilter({ id: dossier.id, label: dossier.dossierName, + checked: dossier.id === dossierId, }), ), checker: keyChecker('dossierId'), }, ]); - - this.addSubscription = _activatedRoute.queryParamMap - .pipe(map(value => ({ query: value.get('query'), dossierId: value.get('dossierId') }))) - .subscribe(mappedValue => this._updateValues(mappedValue)); - - this.addSubscription = this.searchService.valueChanges$.pipe(debounceTime(300)).subscribe(value => this.updateNavigation(value)); - - this.addSubscription = this.filterService.filterGroups$.pipe(skip(1)).subscribe(group => { - const dossierIds = group[0].filters.filter(v => v.checked).map(v => v.id); - this.search$.next({ query: this.searchService.searchValue, dossierIds: dossierIds }); - }); } - updateNavigation(query: string, mustContain?: string): void { - const newQuery = query?.replace(mustContain, `"${mustContain}"`); - const queryParams = newQuery && newQuery !== '' ? { query: newQuery } : {}; - this._router.navigate([], { queryParams }).then(); + private get _searchChanged$(): Observable { + return this.searchService.valueChanges$.pipe( + debounceTime(300), + map(value => ({ query: value, dossierIds: [] })), + ); } - private _search(searchInput: SearchInput): Observable { - return this._platformSearchService.search({ - dossierIds: [...searchInput.dossierIds], - queryString: searchInput.query ?? '', - page: 1, - returnSections: false, - pageSize: 300, - }); + private get _filtersChanged$() { + return this.filterService.filterGroups$.pipe( + map(groups => groups[0].filters.filter(v => v.checked).map(v => v.id)), + map(dossierIds => toSearchInput(this.searchService.searchValue, dossierIds)), + ); } - private _updateValues({ query, dossierId }: { readonly query: string; readonly dossierId: string }) { - if (dossierId) { - this.filterService.toggleFilter('dossiers', dossierId); - } + private get _routeQuery(): ISearchInput { + const query = this._activatedRoute.snapshot.queryParamMap.get('query'); + const dossierId = this._activatedRoute.snapshot.queryParamMap.get('dossierId'); this.searchService.searchValue = query; - this.search$.next({ query, dossierIds: dossierId ? [dossierId] : [] }); + return { query, dossierIds: dossierId ? [dossierId] : [] }; + } + + updateNavigation(query: string) { + return this._router.navigate([], { queryParams: { query } }); + } + + mustContain(value: string) { + const newQuery = this.searchService.searchValue.replace(value, `"${value}"`); + this.searchService.searchValue = newQuery ?? ''; } private _toMatchedDocuments({ matchedDocuments }: ISearchResponse): IMatchedDocument[] { return matchedDocuments.filter(doc => doc.score > 0 && doc.matchedTerms.length > 0); } - private _toListItems(matchedDocuments: IMatchedDocument[]): ListItem[] { + private _toListItems(matchedDocuments: IMatchedDocument[]): ISearchListItem[] { return matchedDocuments.map(document => this._toListItem(document)).filter(value => value); } - private _toListItem({ dossierId, fileId, unmatchedTerms, highlights }: IMatchedDocument): ListItem { + private _toListItem({ dossierId, fileId, unmatchedTerms, highlights, score }: IMatchedDocument): ISearchListItem { const file = this._dossiersService.find(dossierId, fileId); if (!file) { return undefined; @@ -152,7 +142,7 @@ export class SearchScreenComponent extends ListingComponent implements numberOfPages: file.numberOfPages, dossierName: this._dossiersService.find(dossierId).dossierName, filename: file.filename, - searchKey: file.filename, + searchKey: score.toString(), routerLink: `/main/dossiers/${dossierId}/file/${fileId}`, }; } diff --git a/apps/red-ui/src/app/modules/dossier/shared/services/platform-search.service.ts b/apps/red-ui/src/app/modules/dossier/shared/services/platform-search.service.ts index 1eb744b27..19c11d681 100644 --- a/apps/red-ui/src/app/modules/dossier/shared/services/platform-search.service.ts +++ b/apps/red-ui/src/app/modules/dossier/shared/services/platform-search.service.ts @@ -1,6 +1,6 @@ import { Injectable, Injector } from '@angular/core'; import { GenericService } from '@iqser/common-ui'; -import { ISearchRequest, ISearchResponse } from '@red/domain'; +import { ISearchInput, ISearchRequest, ISearchResponse } from '@red/domain'; @Injectable() export class PlatformSearchService extends GenericService { @@ -8,7 +8,13 @@ export class PlatformSearchService extends GenericService { super(_injector, 'search'); } - search(body: ISearchRequest) { - return this._post(body); + search({ dossierIds, query }: ISearchInput) { + return this._post({ + dossierIds, + queryString: query ?? '', + page: 1, + returnSections: false, + pageSize: 300, + } as ISearchRequest); } } diff --git a/apps/red-ui/src/app/modules/shared/shared.module.ts b/apps/red-ui/src/app/modules/shared/shared.module.ts index c98a54456..15067cdb9 100644 --- a/apps/red-ui/src/app/modules/shared/shared.module.ts +++ b/apps/red-ui/src/app/modules/shared/shared.module.ts @@ -56,6 +56,9 @@ const modules = [MatConfigModule, ScrollingModule, IconsModule, FormsModule, Rea { provide: MAT_DATE_FORMATS, useValue: { + parse: { + dateInput: 'DD/MM/YY', + }, display: { dateInput: 'DD/MM/YY', monthYearLabel: 'YYYY', diff --git a/apps/red-ui/src/assets/i18n/de.json b/apps/red-ui/src/assets/i18n/de.json index 2b78704fb..6bddf921c 100644 --- a/apps/red-ui/src/assets/i18n/de.json +++ b/apps/red-ui/src/assets/i18n/de.json @@ -1,114 +1,140 @@ { "actions": { "all": "Alle", - "none": "Keiner" + "none": "Keine" }, "active": "Aktiv", "add-dossier-dialog": { "actions": { - "save": "", - "save-and-add-members": "" + "save": "Speichern", + "save-and-add-members": "Speichern und Team zusammenstellen" }, "errors": { - "dossier-already-exists": "", - "generic": "" + "dossier-already-exists": "Dieser Dossier-Name ist bereits vergeben!", + "generic": "Dossier konnte nicht gespeichert werden." }, "form": { "description": { - "label": "", - "placeholder": "" + "label": "Beschreibung", + "placeholder": "Bitte geben Sie eine Beschreibung ein." }, - "due-date": "", + "due-date": "Termin", "name": { - "label": "", - "placeholder": "" + "label": "Dossier-Name", + "placeholder": "Geben Sie einen Namen ein." }, - "template": "", - "watermark": "" + "template": "Dossier-Vorlage", + "watermark": "Geschwärzte Dokumente mit Wasserzeichen versehen" }, - "header-new": "" + "header-new": "Dossier erstellen" }, "add-edit-dictionary": { "error": { - "dictionary-already-exists": "Wörterbuch mit diesem Namen existiert bereits!", + "dictionary-already-exists": "Ein Wörterbuch mit diesem Namen existiert bereits!", "generic": "Wörterbuch konnte nicht gespeichert werden!", - "invalid-color-or-rank": "Ungültige Farbe oder Rang! Der Rang wird bereits von einem anderen Wörterbuch verwendet oder die Farbe ist keine gültige HexColor!" + "invalid-color-or-rank": "Ungültige Farbe oder Rang! Der Rang wird bereits von einem anderen Wörterbuch verwendet oder die Farbe ist kein gültiger Hex-Farbcode!" }, "form": { - "add-to-dictionary-action": "Verfügbar zum Hinzufügen zum Wörterbuch", - "case-sensitive": "Groß- und Kleinschreibung beachten", - "color": "Hex Farbe", + "add-to-dictionary-action": "Anwender können Einträge hinzufügen", + "case-sensitive": "Groß-/Kleinschreibung berücksichtigen", + "color": "Hex-Farbcode", "color-placeholder": "#", "description": "Beschreibung", "description-placeholder": "Beschreibung eingeben", "hint": "Hinweis", - "name": "Wörterbuchname", - "name-hint": "Kann nach dem Speichern nicht bearbeitet werden.", - "name-placeholder": "Name eingeben", + "name": "Name des Wörterbuches", + "name-hint": "Kann nach dem Speichern nicht mehr bearbeitet werden.", + "name-placeholder": "Namen eingeben", "rank": "Rang", "rank-placeholder": "1000", - "redaction": "Redaktion" + "redaction": "Schwärzung", + "technical-name": "Technischer Name" }, "save": "Wörterbuch speichern", - "title": "" + "title": "{type, select, edit{Wörterbuch {name} bearbeiten} create{Wörterbuch erstellen} other{}}" }, "add-edit-dossier-attribute": { "error": { - "generic": "" + "generic": "Attribut konnte nicht gespeichert werden!" }, "form": { - "label": "", - "label-placeholder": "", - "placeholder": "", - "type": "" + "label": "Name des Attributs", + "label-placeholder": "Namen eingeben", + "placeholder": "Platzhalter für Attribut", + "type": "Attributtyp" }, - "save": "", - "title": "" + "save": "Attribut speichern", + "title": "{type, select, edit{Dossier-Attribut {name} bearbeiten} create{Neues Dossier-Attribut hinzufügen} other{}}" }, "add-edit-dossier-template": { + "error": { + "conflict": "Dossiervorlage konnte nicht erstellt werden: Es existiert bereits eine Dossiervorlage mit demselben Namen.", + "generic": "Fehler beim Erstellen der Dossiervorlage." + }, "form": { "description": "Beschreibung", "description-placeholder": "Beschreibung eingeben", - "name": "Name der Dossiervorlage", - "name-placeholder": "Name eingeben", + "name": "Name der Dossier-Vorlage", + "name-placeholder": "Namen eingeben", "valid-from": "Gültig ab", "valid-to": "Gültig bis" }, - "save": "Speichern Sie die Dossiervorlage", - "title": "" + "save": "Dossier-Vorlage speichern", + "title": "{type, select, edit{Dossier-Vorlage {name} bearbeiten} create{Dossier-Vorlage erstellen} other{}}" }, "add-edit-file-attribute": { "form": { "column-header": "CSV-Spaltenüberschrift", - "column-header-placeholder": "Geben Sie den CSV-Spaltenkopf ein", - "name": "Attributname", - "name-placeholder": "Name eingeben", - "primary": "Als primär festlegen", - "read-only": "Schreibgeschützt machen", - "type": "Art" + "column-header-placeholder": "Spaltenüberschrift für CSV eingeben", + "displayedInFileList": "Wird in der Dokumentenliste angezeigt", + "filterable": "Filterbar", + "name": "Name des Attributs", + "name-placeholder": "Namen eingeben", + "primary": "Zum Primärattribut machen", + "read-only": "Schreibgeschützt", + "type": "Typ" }, "save": "Attribut speichern", - "title": "" + "title": "{type, select, edit{Edit {name}} create{Add New} other{}} Datei-Attribut" + }, + "add-edit-justification": { + "actions": { + "cancel": "Abbrechen", + "save": "Begründung speichern" + }, + "form": { + "description": "Beschreibung", + "description-placeholder": "Beschreibung eingeben", + "name": "Name", + "name-placeholder": "Name eingeben", + "reason": "Rechtliche Grundlage", + "reason-placeholder": "Rechtsgrundlage eingeben" + }, + "title": "{type, select, edit{Edit {name}} create{Add New} other{}} Begründung" }, "add-edit-user": { "actions": { - "cancel": "Stornieren", + "cancel": "Abbrechen", "delete": "Benutzer löschen", "save": "Benutzer speichern", "save-changes": "Änderungen speichern" }, + "error": { + "email-already-used": "Diese E-Mail-Adresse wird bereits von einem anderen Benutzer verwendet!", + "generic": "Benutzer konnte nicht gespeichert werden!" + }, "form": { - "email": "Email", + "email": "E-Mail", "first-name": "Vorname", "last-name": "Nachname", - "reset-password": "", + "reset-password": "Passwort zurücksetzen", "role": "Rolle" }, - "title": "" + "title": "{type, select, edit{Benutzer bearbeiten} create{Neuen Benutzer hinzufügen} other{}}" }, "admin-side-nav": { - "dossier-templates": "", - "settings": "" + "dossier-templates": "Dossier-Vorlage", + "settings": "Einstellungen" }, "annotation": "Anmerkung", "annotation-actions": { @@ -116,280 +142,345 @@ "label": "Empfehlung annehmen" }, "accept-suggestion": { - "label": "Vorschlag annehmen" + "label": "Genehmigen und zum Wörterbuch hinzufügen", + "add-to-dict": "Genehmigen und zum Wörterbuch hinzufügen", + "only-here": "Nur hier genehmigen", + "remove-from-dict": "Genehmigen und aus dem Wörterbuch löschen." }, "edit-reason": { - "label": "" + "label": "Begründung bearbeiten" }, "force-redaction": { - "label": "Redaktion erzwingen" + "label": "Schwärzung erzwingen" }, "hide": "Ausblenden", "message": { "dictionary": { "add": { - "error": "Fehler beim Hinzufügen des Eintrags zum Wörterbuch: {error}", - "success": "Eintrag zum Wörterbuch hinzugefügt. Änderungen werden nach einer erneuten Analyse sichtbar." + "conflict-error": "''{content}'' kann nicht zum {dictionaryName}-Wörterbuch hinzugefügt werden, da es als allgemeiner Begriff erkannt wurde, der zu oft in Texten vorkommt.", + "error": "Fehler beim Hinzufügen des neuen Wörterbucheintrags: {error}", + "success": "Eintrag zum Wörterbuch hinzugefügt. Änderungen nach der Reanalyse sichtbar." }, "approve": { - "error": "Wörterbucheintrag konnte nicht genehmigt werden: {error}", - "success": "Wörterbucheintrag genehmigt. Änderungen werden nach einer erneuten Analyse sichtbar." + "error": "Fehler beim Genehmigen des Wörterbucheintrags: {error}", + "success": "Neuer Wörterbucheintrag wurde genehmigt. Änderungen sind nach der Reanalyse sichtbar." }, "decline": { - "error": "Fehler beim Ablehnen des Wörterbuchvorschlags: {error}", - "success": "Wörterbuchvorschlag abgelehnt." + "error": "Fehler beim Ablehnen des neuen Wörterbucheintrags: {error}", + "success": "Vorschlag für das Wörterbuch abgelehnt." }, "remove": { "error": "Fehler beim Entfernen des Wörterbucheintrags: {error}", - "success": "Wörterbucheintrag entfernt!" + "success": "Wörterbucheintrag wurde gelöscht!" }, "request-remove": { - "error": "Das Entfernen des Wörterbucheintrags konnte nicht angefordert werden: {error}", - "success": "Angefordert, Wörterbucheintrag zu entfernen!" + "error": "Dossier-Vorlage", + "success": "Löschung des Wörterbucheintrags wurde vorgeschlagen!" }, "suggest": { - "error": "Vorschlag zum Ändern des Wörterbuchs konnte nicht gespeichert werden: {error}", - "success": "Vorschlag zur Wörterbuchänderung gespeichert!" + "error": "Vorschlag für Änderung des Wörterbuchs konnte nicht gespeichert werden: {error}", + "success": "Vorschlag für die Änderung des Wörterbuchs gespeichert!" }, "undo": { - "error": "Fehler beim Rückgängigmachen: {error}", - "success": "Rückgängig machen erfolgreich" + "error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}", + "success": "Rückgängigmachen erfolgreich" } }, "manual-redaction": { "add": { - "error": "Fehler beim Speichern der Redaktion: {error}", - "success": "Redaktion hinzugefügt!" + "error": "Fehler beim Speichern der Schwärzung: {error}", + "success": "Schwärzung hinzugefügt!" }, "approve": { - "error": "Fehler beim Genehmigen der Redaktion: {error}", - "success": "Redaktionsvorschlag genehmigt!" + "error": "Fehler beim Genehmigen des Vorschlags: {error}", + "success": "Vorschlag genehmigt" }, "change-legal-basis": { - "error": "", - "success": "" + "error": "Fehler beim Bearbeiten der in der Anmerkung genannten Begründung: {error}", + "success": "In der Anmerkung genannte Begründung wurde bearbeitet." }, "decline": { - "error": "Redaktion konnte nicht abgelehnt werden: {error}", - "success": "Redaktionsvorschlag abgelehnt!" + "error": "Fehler beim Ablehnen des Vorschlags: {error}", + "success": "Vorschlag abgelehnt" }, "force-redaction": { - "error": "", - "success": "" + "error": "Die Schwärzung konnte nicht gespeichert werden!", + "success": "Schwärzung eingefügt!" }, "recategorize-image": { - "error": "", - "success": "" + "error": "Rekategorisierung des Bildes gescheitert: {error}", + "success": "Bild wurde einer neuen Kategorie zugeordnet." + }, + "remove": { + "error": "Fehler beim Entfernen der Schwärzung: {error}", + "success": "Schwärzung entfernt!" }, "request-change-legal-basis": { - "error": "", - "success": "" + "error": "Fehler beim Vorschlagen der Änderung der Begründung:", + "success": "Die Änderung der in der Anmerkung genannten Begründung wurde beantragt." }, "request-force-redaction": { - "error": "", - "success": "" + "error": "Fehler beim Speichern des Schwärzungsvorschlags: {error}", + "success": "Vorschlag einer Schwärzung gespeichert" }, "request-image-recategorization": { - "error": "", - "success": "" + "error": "Fehler beim Vorschlagen der Neukategorisierung des Bilds: {error}", + "success": "Bild-Neuklassifizierung angefordert." + }, + "request-remove": { + "error": "Fehler beim Erstellen des Vorschlags für das Entfernen der Schwärzung: {error}", + "success": "Entfernen der Schwärzung wurde vorgeschlagen!" }, "suggest": { - "error": "Fehler beim Speichern des Redaktionsvorschlags: {error}", - "success": "Redaktionsvorschlag gespeichert" + "error": "Vorschlag einer Schwärzung wurde nicht gespeichert: {error}", + "success": "Vorschlag einer Schwärzung gespeichert" }, "undo": { - "error": "Fehler beim Rückgängigmachen: {error}", - "success": "Rückgängig machen erfolgreich" - } + "error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}", + "success": "erfolgreich Rückgängig gemacht" + }, + "search": "Dokumentname..." } }, - "recategorize-image": "", + "recategorize-image": "neu kategorisieren", "reject-suggestion": "Vorschlag ablehnen", "remove-annotation": { "false-positive": "Falsch positiv", - "only-here": "Nur hier entfernen", - "remove-from-dict": "Aus dem Wörterbuch entfernen" + "only-here": "nur hier entfernen", + "remove-from-dict": "Aus dem Wörterbuch entfernen", + "suggest-only-here": "Vorschlagen, nur hier zu entfernen", + "suggest-remove-from-dict": "Vorschlagen, aus dem Wörterbuch zu entfernen" }, - "show": "Show", - "undo": "Rückgängig machen" + "show": "Zeigen", + "undo": "Rückgängig", + "reject": "Ablehnen", + "remove": "entfernen", + "suggest-remove-annotation": "Entfernen oder vorschlagen, diesen Eintrag zu entfernen", + "suggest-remove-annotations": "Ausgewählte Einträge löschen bzw. Löschung vorschlagen" + }, + "annotation-engines": { + "dictionary": "{isHint, select, true{Hint} other{Redaction}} basierend auf Wörterbuch", + "ner": "Redaktion basierend auf KI", + "rule": "Schwärzung basierend auf Regel {rule}" }, "annotation-type": { - "add-dictionary": "Ausstehend zum Wörterbuch hinzufügen", - "change-legal-basis": "", + "add-dictionary": "Ausstehende Ergänzung zum Wörterbuch", + "change-legal-basis": "Änderung der Rechtsgrundlage ausstehend", "declined-suggestion": "Abgelehnter Vorschlag", "hint": "Hinweis", - "manual-redaction": "Manuelle Redaktion", - "pending-analysis": "Bis zur erneuten Analyse", + "manual-redaction": "Manuelle Schwärzung", + "pending-analysis": "Reanalyse ausstehend", "recommendation": "Empfehlung", - "redaction": "Redaktion", - "remove-dictionary": "Ausstehend aus dem Wörterbuch entfernen", - "remove-only-here": "Ausstehende Entfernung (nur hier)", + "redaction": "Schwärzung", + "remove-dictionary": "Ausstehende Löschung aus dem Wörterbuch", + "remove-only-here": "Ausstehende Löschung (nur hier)", "skipped": "Übersprungen", - "suggestion-add": "Vorgeschlagene Redaktion", - "suggestion-add-dictionary": "Vorgeschlagenes Wörterbuch hinzufügen", - "suggestion-change-legal-basis": "", - "suggestion-force-redaction": "Redaktion der Vorschlagskraft", - "suggestion-recategorize-image": "", - "suggestion-remove": "Vorgeschlagene Redaktionsentfernung", - "suggestion-remove-dictionary": "Vorgeschlagene Wörterbuchentfernung" + "suggestion-add": "Vorschlag für Schwärzung", + "suggestion-add-dictionary": "Vorschlag für neuen Wörterbucheintrag", + "suggestion-change-legal-basis": "Vorschlag für Änderung der Rechtsgrundlage", + "suggestion-force-redaction": "Vorschlag für erzwungene Schwärzung", + "suggestion-recategorize-image": "Vorschlag für Rekategorisierung eines Bilds", + "suggestion-remove": "Vorschlagen, die Schwärzung zu entfernen", + "suggestion-remove-dictionary": "Vorschlag für Löschung eines Wörterbucheintrags" }, "annotations": "Anmerkungen", "archived": "Archiviert", "assign-dossier-owner": { "dialog": { - "approvers": "", - "make-approver": "", - "no-approvers": "", - "no-reviewers": "", - "reviewers": "", - "search": "Suche...", - "single-user": "Inhaber" + "approvers": "Genehmiger", + "make-approver": "Zum Genehmiger ernennen", + "no-approvers": "Es gibt noch keine Genehmiger. Bitte aus der Listen unten auswählen.", + "no-reviewers": "Es gibt noch keine Reviewer.\nBitte aus der Liste unten auswählen.", + "reviewers": "Reviewer", + "search": "Suche ...", + "single-user": "Besitzer", + "cancel": "Abbrechen", + "multi-user": "Review-Team", + "save": "Änderungen speichern", + "title": "Dossier-Team verwalten" } }, "assign-owner": { "dialog": { - "cancel": "", - "label": "", - "save": "", - "title": "" + "cancel": "Abbrechen", + "label": "{type, select, approver{Genehmiger} reviewer{Reviewer} other{}}", + "save": "Speichern", + "title": "Datei verwalten: {type, select, approver{Genehmiger} reviewer{Reviewer} other{}}" } }, "assign-user": { - "cancel": "", - "save": "" + "cancel": "Abbrechen", + "save": "Speichern" }, - "audit": "Prüfung", + "assignment": { + "owner": "{ownerName} wurde erfolgreich zum Dossier {dossierName} hinzugefügt.", + "reviewer": "{reviewerName} wurde erfolgreich zum Dokument {filename} hinzugefügt." + }, + "audit": "Aktivitätenprotokoll", "audit-screen": { - "all-users": "Alle Nutzer", + "all-users": "Alle Benutzer", "categories": { - "all-categories": "", - "audit": "", - "audit-log": "", - "dictionary": "", - "document": "", - "dossier": "", - "dossier-template": "", - "download": "", - "license": "", - "project": "", - "project-template": "", - "user": "" + "all-categories": "Alle Bereiche", + "audit": "Aktivitätenprotokoll", + "audit-log": "Aktivitätenprotokoll", + "dictionary": "Wörterbuch", + "document": "Dokument", + "dossier": "Dossier", + "dossier-template": "Dossier-Vorlage", + "download": "Download", + "license": "Lizenz", + "project": "Projekt", + "project-template": "Projekt-Vorlage", + "user": "Nutzer" }, "no-data": { - "title": "Keine verfügbaren Protokolle." + "title": "Keine Protokolle verfügbar." }, "table-col-names": { "category": "Kategorie", "date": "Datum", - "message": "Botschaft", - "user": "Benutzer" + "message": "Nachricht", + "user": "Nutzer" }, "table-header": { - "title": "{length} Protokolle" + "title": "{length} {length, plural, one{Log} other{Logs}}" }, - "to": "zu" + "to": "bis", + "all-categories": "Alle Bereiche" }, "auth-error": { - "heading": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie Ihren Administrator für den Zugriff!", - "heading-with-link": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie Ihren Administrator für den Zugriff!", - "heading-with-name": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie {adminName} für den Zugriff!", - "heading-with-name-and-link": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie {adminName} für den Zugriff!", + "heading": "Ihr Benutzer verfügt nicht über die erforderlichen RED-*-Rollen, um auf diese Applikation zugreifen zu können. Bitte kontaktieren Sie Ihren Admin, um den Zugang anzufordern!", + "heading-with-link": "Ihr Benutzer verfügt nicht über die erforderlichen RED-*-Rollen, um auf diese Applikation zugreifen zu können. Bitte kontaktieren Sie Ihren Admin, um den Zugang anzufordern!", + "heading-with-name": "Ihr Benutzer verfügt nicht über die erforderlichen RED-*-Rollen, um auf diese Applikation zugreifen zu können. Bitte kontaktieren Sie {adminName}, um den Zugang anzufordern!", + "heading-with-name-and-link": "Ihr Benutzer verfügt nicht über die erforderlichen RED-*-Rollen, um auf diese Applikation zugreifen zu können. Bitte kontaktieren Sie {adminName}, um den Zugang anzufordern!", "logout": "Ausloggen" }, - "by": "durch", + "by": "von", "change-legal-basis-dialog": { "actions": { - "cancel": "", - "save": "" + "cancel": "Abbrechen", + "save": "Änderungen speichern" }, "content": { - "comment": "", - "legalBasis": "", - "reason": "", - "reason-placeholder": "" + "comment": "Kommentar", + "legalBasis": "Rechtsgrundlage", + "reason": "Begründung für die Schwärzung auswählen", + "reason-placeholder": "Wählen Sie eine Begründung aus ..." }, - "header": "" + "header": "Begründung für die Schwärzung bearbeiten" }, "comments": { - "add-comment": "Einen Kommentar hinzufügen", - "comments": "{count} Kommentare", - "hide-comments": "Ausblenden" + "add-comment": "Kommentar eingeben", + "comments": "{count} {count, plural, one{Kommentar} other{Kommentare}}", + "hide-comments": "Kommentare verbergen", + "cancel": "Abbrechen", + "comment": "{{count}} Kommentar(e)" }, "common": { "close": "Ansicht schließen", "confirmation-dialog": { "confirm": "Ja", "deny": "Nein", - "description": "Diese Aktion muss bestätigt werden. Möchten Sie fortfahren?", + "description": "Diese Aktion erfordert eine Bestätigung. Möchten Sie fortfahren?", "title": "Aktion bestätigen" + }, + "dialog": { + "close": "Dialog schließen" } }, - "configurations": "Konfigurationen", + "configurations": "Einstellungen", "confirm-delete-file-attribute": { - "cancel": "", - "delete": "", - "impacted-documents": "", - "lost-details": "Alle eingegebenen Details in den Dokumenten gehen verloren", - "title": "", - "toast-error": "Bitte bestätigen Sie, dass Sie die Auswirkungen Ihrer Handlung verstehen!", - "warning": "Achtung: Dies kann nicht rückgängig gemacht werden!" + "cancel": "{type, select, single{Attribut} bulk{Attribute} other{}} behalten", + "delete": "{type, select, single{Attribut} bulk{Attribute} other{}} löschen", + "impacted-documents": "Alle Dokumente {type, select, single{ist} bulk{sind} other{}} betroffen", + "lost-details": "Alle in die Dokumente eingegebenen Daten gehen verloren", + "title": "{type, select, single{{name}} bulk{Datei-Attribute} other{}} löschen", + "toast-error": "Bitte bestätigen Sie, dass Ihnen die Konsequenzen dieser Aktion bewusst sind!", + "warning": "Achtung: Diese Aktion kann nicht rückgängig gemacht werden!" }, "confirm-delete-users": { - "cancel": "", - "delete": "", - "impacted-documents": "", - "impacted-dossiers": "{dossiersCount} Dossiers sind betroffen", - "title": "", - "toast-error": "Bitte bestätigen Sie, dass Sie die Auswirkungen Ihrer Handlung verstehen!", - "warning": "Achtung: Dies kann nicht rückgängig gemacht werden!" + "cancel": "{usersCount, plural, one{Benutzer} other{Benutzer}} behalten", + "delete": "{usersCount, plural, one{Benutzer} other{Benutzer}} löschen", + "impacted-documents": "Betroffen sind alle Dokumente, deren Review durch den/die {usersCount, plural, one{user} other{users}} noch aussteht", + "impacted-dossiers": "{dossiersCount} {dossiersCount, plural, one{Dossier} other{Dossiers}} sind betroffen", + "title": "{usersCount, plural, one{Benutzer} other{Benutzer}} aus dem Arbeitsbereich entfernen", + "toast-error": "Bitte bestätigen Sie, dass Ihnen die Konsequenzen dieser Aktion bewusst sind!", + "warning": "Achtung: Diese Aktion kann nicht rückgängig gemacht werden!" }, "confirmation-dialog": { + "approve-file": { + "question": "Dieses Dokument enthält ungesehene Änderungen. Möchten Sie es trotzdem genehmigen?", + "title": "Warnung!" + }, + "approve-multiple-files": { + "question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen. Möchten Sie sie trotzdem genehmigen?", + "title": "Warnung!" + }, "assign-file-to-me": { - "question": "Dieses Dokument wird derzeit von einer anderen Person geprüft. Möchten Sie der Prüfer werden und sich diesem Dokument zuordnen?", - "title": "Prüfer neu zuweisen" + "question": "Dieses Dokument wird gerade von einer anderen Person geprüft. Möchten Sie Reviewer werden und sich selbst dem Dokument zuweisen?", + "title": "Neuen Reviewer zuweisen" }, "compare-file": { - "question": "", - "title": "" + "question": "Achtung!

Seitenzahl stimmt nicht überein, aktuelles Dokument hat {currentDocumentPageCount} Seite(n). Das hochgeladene Dokument hat {compareDocumentPageCount} Seite(n).

Möchten Sie fortfahren?", + "title": "Vergleichen mit: {fileName}" }, "delete-dossier": { - "confirmation-text": "Lösche Dossier", - "deny-text": "", - "input-label": "", - "question": "Möchten Sie fortfahren?", - "title": "Dossier {dossierName}" + "confirmation-text": "Dossier löschen", + "deny-text": "Dossier behalten", + "question": "Möchten Sie dieses Dokument wirklich löschen?", + "title": "{dossierName} löschen", + "details": "Gelöschte Dossiers werden in Papierkorb verschoben. Sie können bis zu {{period}} Tage nach dem Löschen wiederhergestellt werden.", + "input-label": "Zum Fortzufahren bitte unten tippen" }, "delete-file": { "question": "Möchten Sie fortfahren?", "title": "Dokument löschen" + }, + "delete-justification": { + "question": "Möchten Sie {count, plural, one{diese Begründung} other{diese Begründung}} wirklich löschen?", + "title": "{count, plural, one{{justificationName}} other{ausgewählte Begründungen}} löschen" + }, + "input-label": "Bitte geben Sie unten Folgendes ein, um fortzufahren", + "permanently-delete-file": { + "confirmation-text": "{filesCount, plural, one{Document} other{Documents}} löschen", + "deny-text": "{filesCount, plural, one{Dokument} other{Dokumente}} behalten", + "question": "Möchten Sie {filesCount, plural, one{dieses Dokument} other{diese Dokumente}} wirklich löschen?", + "title": "{filesCount, plural, one{{fileName}} other{ausgewählte Dokumente}} löschen" + }, + "upload-report-template": { + "alternate-confirmation-text": "Als Bericht für mehrere Dokumente hochladen", + "confirmation-text": "Als Bericht für ein Dokument hochladen", + "deny-text": "Uploads abbrechen", + "question": "Wählen Sie bitte aus, ob {fileName} eine Berichtsvorlage für eine oder für mehrere Dateien ist", + "title": "Upload der Berichtsvorlage" } }, - "content": "Grund", - "default-colors": "Standardfarben", + "content": "Begründung", + "default-colors": "Farbeinstellungen", "default-colors-screen": { "action": { "edit": "Farbe bearbeiten" }, "table-col-names": { "color": "Farbe", - "key": "Art" + "key": "Typ" }, "table-header": { - "title": "{length} Standardfarben" + "title": "{length} Standard{length, plural, one{farbe} other{farben}}" }, "types": { "analysisColor": "Analyse", "defaultColor": "Standardfarbe", - "dictionaryRequestColor": "Wörterbuchanforderung", - "manualRedactionColor": "Manuelle Redaktion", + "dictionaryRequestColor": "Wörterbuch", + "manualRedactionColor": "Manuelle Schwärzung", "notRedacted": "Übersprungen", "previewColor": "Vorschau", - "requestAdd": "Anfrage hinzufügen", - "requestRemove": "Anfrage entfernen", + "requestAdd": "Neuen Wörterbucheintrag vorschlagen", + "requestRemove": "Anfrage entfernt", "updatedColor": "Aktualisiert" } }, - "dev-mode": "[DEV-MODUS]", + "dev-mode": "DEV", "dictionaries": "Wörterbücher", "dictionary": "Wörterbuch", "dictionary-listing": { @@ -399,17 +490,17 @@ }, "add-new": "Neues Wörterbuch", "bulk": { - "delete": "" + "delete": "Ausgewählte Wörterbücher löschen" }, - "case-sensitive": "Groß- und Kleinschreibung beachten", + "case-sensitive": "Klein-/Großschreibung berücksichtigen", "no-data": { "action": "Neues Wörterbuch", "title": "Es gibt noch keine Wörterbücher." }, "no-match": { - "title": "Keine Wörterbücher stimmen mit Ihren aktuellen Filtern überein." + "title": "Die ausgewählten Filter treffen auf kein Wörterbuch zu." }, - "search": "Suche...", + "search": "Suche ...", "stats": { "charts": { "entries": "Einträge", @@ -417,12 +508,13 @@ } }, "table-col-names": { - "hint-redaction": "Hinweis / Redaktion", - "rank": "Reihenfolge der Wichtigkeit", - "type": "Art" + "hint-redaction": "Hinweis/Schwärzung", + "rank": "Rang", + "type": "Typ", + "order-of-importance": "Rangfolge" }, "table-header": { - "title": "{length} Wörterbücher" + "title": "{length} {length, plural, one{Wörterbuch} other{Wörterbücher}}" } }, "dictionary-overview": { @@ -433,45 +525,45 @@ "upload": "Wörterbuch hochladen" }, "compare": { - "compare": "Vergleichen Sie", - "select-dossier": "Wählen Sie Dossiervorlage", - "select-dossier-template": "", - "select-dictionary": "" + "compare": "Vergleichen", + "select-dictionary": "Wörterbuch auswählen", + "select-dossier": "Dossier auswählen", + "select-dossier-template": "Dossiervorlage auswählen" }, "dictionary-details": { "description": "Beschreibung" }, "error": { - "entries-too-short": "Einige Einträge des Wörterbuchs liegen unter der Mindestlänge von 2. Diese sind rot hervorgehoben!", - "generic": "Etwas ist schief gelaufen ... Wörterbuch-Update fehlgeschlagen!" + "entries-too-short": "Einige Einträge im Wörterbuch unterschreiten die Mindestlänge von 2 Zeichen. Diese sind rot markiert.", + "generic": "Es ist ein Fehler aufgetreten ... Das Wörterbuch konnte nicht aktualisiert werden!" }, - "revert-changes": "Zurückkehren", + "revert-changes": "Rückgängig machen", "save-changes": "Änderungen speichern", - "search": "Suche...", - "select-dictionary": "Wählen Sie oben ein Wörterbuch aus, um es mit dem aktuellen zu vergleichen.", + "search": "Suche ...", + "select-dictionary": "Wählen Sie oben das Wörterbuch aus, das Sie mit dem aktuellen Wörterbuch vergleichen möchten.", "success": { "generic": "Wörterbuch aktualisiert!" } }, - "digital-signature": "Digitale Unterschrift", + "digital-signature": "Digitale Signatur", "digital-signature-screen": { "action": { - "certificate-not-valid-error": "Das hochgeladene Zertifikat gilt nicht zum Signieren von PDFs. Das PCKS.12-Format ist erforderlich.", + "certificate-not-valid-error": "Das hochgeladene Zertifikat eignet sich nicht zum Signieren von PDF-Dokumenten. Sie benötigen das Format PCKS#12.", "delete": "Digitale Signatur löschen", - "delete-error": "Fehler beim Entfernen der digitalen Signatur. Versuchen Sie es erneut.", - "delete-success": "Digitale Signatur entfernt. Redigierte Dateien werden nicht mehr signiert!", + "delete-error": "Die digitale Signatur konnte nicht entfernt werden, bitte versuchen Sie es erneut.", + "delete-success": "Die digitale Signatur wurde gelöscht. Geschwärzte Dateien werden nicht länger mit einer Signatur versehen!", "reset": "Zurücksetzen", "save": "Digitale Signatur speichern", "save-error": "Fehler beim Speichern der digitalen Signatur", "save-success": "Digitale Signatur erfolgreich gespeichert" }, "certificate-name": { - "label": "Zertifikatname", - "placeholder": "Zertifikatname" + "label": "Name des Zertifikats", + "placeholder": "Name des Zertifikats" }, "contact-info": { - "label": "Kontakt Informationen", - "placeholder": "Kontakt Informationen" + "label": "Kontaktdaten", + "placeholder": "Kontaktdaten" }, "location": { "label": "Ort", @@ -479,228 +571,273 @@ }, "no-data": { "action": "Zertifikat hochladen", - "title": "Es ist kein Zertifikat für digitale Signatur konfiguriert. Laden Sie zum Signieren redigierter Dokumente ein PCKS.12-Zertifikat hoch." + "title": "Es ist kein Zertifikat für die digitale Signatur konfiguriert. Laden Sie ein PCKS#12-Zertifikat hoch, um Ihre geschwärzten Dokumente zu signieren." }, "password": { - "label": "Zertifikat Passwort / Schlüssel", + "label": "Zertifikatspasswort/-schlüssel", "placeholder": "Passwort" }, "reason": { - "label": "Grund", - "placeholder": "Grund" - } + "label": "Begründung", + "placeholder": "Begründung" + }, + "title": "Digitale Signatur" }, "document-info": { - "save": "Dokumentinformationen speichern", - "title": "Dateiattribute einführen" + "save": "Dokumenteninformation speichern", + "title": "Datei-Attribute anlegen", + "save-approval": "Speichern und in Genehmigung geben" }, + "dossier": "Dossier", "dossier-attribute-types": { - "date": "", - "image": "", - "number": "", - "text": "" + "date": "Datum", + "image": "Bild", + "number": "Nummer", + "text": "Text" }, - "dossier-attributes": "", + "dossier-attributes": "Dossier-Attribut", "dossier-attributes-listing": { "action": { - "delete": "", - "edit": "" + "delete": "Attribut löschen", + "edit": "Attribut bearbeiten" }, - "add-new": "", + "add-new": "Neues Attribut", "bulk": { - "delete": "" + "delete": "Ausgewähltes Attribut löschen" }, "no-data": { - "action": "", - "title": "" + "action": "Neues Attribut", + "title": "Es sind keine Dossier-Attribute vorhanden" }, "no-match": { - "title": "" + "title": "Die ausgewählten Filter treffen auf kein Attribut zu." }, - "search": "", + "search": "Suche ...", "table-col-names": { - "label": "", - "placeholder": "", - "type": "" + "label": "Label", + "placeholder": "Platzhalter", + "type": "Typ" }, "table-header": { - "title": "" + "title": "{length} {length, plural, one{Dossier-Attribut} other{Dossier-Attribute}}" } }, "dossier-details": { "assign-members": "Mitglieder zuweisen", "collapse": "Details ausblenden", - "edit-owner": "", - "expand": "Zeige Details", + "edit-owner": "Eigentümer bearbeiten", + "expand": "Details zeigen", "members": "Mitglieder", - "owner": "Inhaber", - "see-less": "Weniger sehen", - "title": "Dossier Details" - }, - "dossier-dictionary-dialog": { - "cancel": "", - "save-changes": "", - "title": "" + "owner": "Eigentümer", + "see-less": "Weniger anzeigen", + "title": "Dossier-Details", + "dialog": { + "actions": { + "reanalyse-dossier": "Dossier analysieren" + }, + "info": { + "file-count": "Anzahl der Dateien: {{fileCount}}" + }, + "title": "Dossier-Details" + } }, "dossier-listing": { "add-new": "Neues Dossier", "delete": { "action": "Dossier löschen", - "delete-failed": "Fehler beim Löschen des Dossiers: {dossierName}" + "delete-failed": "Das Dossier {dossierName} konnte nicht gelöscht werden" }, "edit": { "action": "Dossier bearbeiten" }, - "no-data": { - "action": "Neues Dossier", - "title": "Sie haben derzeit keine Dossiers." - }, - "no-match": { - "title": "Keine Dossiers stimmen mit Ihren aktuellen Filtern überein." - }, - "quick-filters": { - "my-dossiers": "", - "other": "", - "to-approve": "", - "to-review": "" - }, - "reanalyse": { - "action": "Analysieren Sie das gesamte Dossier" - }, "filters": { "label": "Dossiername", "search": "Dossiername..." }, + "no-data": { + "action": "Neues Dossier", + "title": "Sie haben momentan keine Dossiers." + }, + "no-match": { + "title": "Die ausgewählten Filter treffen auf kein Dossier zu." + }, + "quick-filters": { + "my-dossiers": "Meine Dossiers", + "other": "Sonstige", + "to-approve": "Zu Genehmigen", + "to-review": "Zu Überprüfen" + }, + "reanalyse": { + "action": "Gesamtes Dossier analysieren" + }, "stats": { "analyzed-pages": "Seiten", "charts": { "dossiers": "Dossiers", - "total-documents": "Gesamtdokument (e)" + "total-documents": "Anzahl der Dokumente" }, - "total-people": "Benutzer insgesamt" + "total-people": "Anzahl der Benutzer" }, "table-col-names": { "name": "Name", - "needs-work": "Arbeitsbelastung", - "owner": "Inhaber", + "needs-work": "Arbeitsvorrat", + "owner": "Besitzer", "status": "Status" }, "table-header": { - "title": "{length} aktive Dossiers" - } + "title": "{length} {length, plural, one{aktives Dossier} other{aktive Dossiers}}", + "bulk-select": "Auswahl umkehren", + "recent": "Neu" + }, + "download-files": { + "action": "Geschwärzte Dossiers herunterladen" + }, + "header": "Dossier", + "search": "Dossier-Name ..." }, "dossier-overview": { "approve": "Genehmigen", - "approve-disabled": "Die Datei kann erst genehmigt werden, wenn sie mit den neuesten Wörterbüchern analysiert und alle Vorschläge verarbeitet wurden.", - "assign-approver": "", - "assign-me": "Zuweisen zu mir", - "assign-reviewer": "", + "approve-disabled": "Das Dokument kann erst genehmigt werden, wenn eine Analyse auf Basis der aktuellen Wörterbücher durchgeführt wurde und die Vorschläge bearbeitet wurden.", + "assign-approver": "Genehmiger zuordnen", + "assign-me": "Mir zuteilen", + "assign-reviewer": "Überprüfer zuordnen", "bulk": { "delete": "Dokumente löschen", - "reanalyse": "Dokumente analysieren" + "reanalyse": "Dokumente analysieren", + "assign": "Überprüfer zuordnen", + "reanalyse-error-outdated": "Nicht alle ausgewählten Dokumente können analysiert werden, manche sind Ihnen möglicherweise nicht zugeordnet oder wurden bereits analysiert." }, "delete": { "action": "Datei löschen" }, "dossier-details": { "attributes": { - "expand": "", - "image-uploaded": "", - "show-less": "" + "expand": "{count} {count, plural, one{benutzerdefiniertes Attribut} other{benutzerdefinierte Attribute}}", + "image-uploaded": "Bild hochgeladen", + "show-less": "weniger anzeigen" }, "charts": { "documents-in-dossier": "Dokumente im Dossier" }, "description": "Beschreibung", - "dictionary": "", + "dictionary": "Dossier-Wörterbuch", "stats": { - "analysed-pages": "{count} Seiten", + "analysed-pages": "{count} {count, plural, one{Seite} other{Seiten}}", "created-on": "Erstellt am {date}", - "documents": "{count} Dokumente", - "due-date": "Geburtstermin", - "people": "{count} Benutzer", - "deleted": "{count} " + "deleted": "{count} gelöschte Dateien", + "documents": "{count} {count, plural, one{Dokument} other{Dokumente}}", + "due-date": "Fällig am {date}", + "people": "{count} {count, plural, one{Benutzer} other{Benutzer}}" } }, "download-file": "Herunterladen", - "download-file-disabled": "Das Herunterladen ist nur für genehmigte Dateien zulässig", + "download-file-disabled": "Nur genehmigte Dateien können heruntergeladen werden", "file-listing": { "file-entry": { - "file-error": "Nachbearbeitung erforderlich", - "file-pending": "Steht aus...", - "file-processing": "wird bearbeitet" + "file-error": "Reanalyse erforderlich", + "file-pending": "Ausstehend ...", + "file-processing": "Wird analysiert", + "added": "Datum hinzugefügt: {{added}}", + "last-updated": "Zuletzt aktualisiert: {{lastUpdated}}", + "number-of-analyses": "Anzahl der Analysen: {{numberOfAnalyses}}", + "number-of-pages": "Anzahl der Seiten: {{numberOfPages}}", + "status": "Status: {{status}}" } }, - "header-actions": { - "edit": "Bearbeiten", - "upload-document": "Dokument hochladen" - }, - "new-rule": { - "toast": { - "actions": { - "reanalyse-all": "Analysieren Sie alle" - } - } - }, - "no-data": { - "action": "Dokument hochladen", - "title": "Es liegen noch keine Dokumente vor." - }, - "no-match": { - "title": "Keine Dokumente stimmen mit Ihren aktuellen Filtern überein." - }, - "ocr-file": "OCR-Dokument", - "ocr-performed": "Für diese Datei wurde eine OCR durchgeführt.", - "quick-filters": { - "assigned-to-me": "", - "assigned-to-others": "", - "recent": "", - "unassigned": "" - }, - "reanalyse-dossier": { - "error": "Dateien für die erneute Analyse konnten nicht geplant werden. Bitte versuche es erneut.", - "success": "Dateien, die erneut analysiert werden sollen." - }, - "reanalyse": { - "action": "Datei analysieren" - }, "filters": { "label": "Dokumentname", "search": "Dokumentname..." }, + "header-actions": { + "download-csv": "CSV-Dateibericht herunterladen", + "edit": "Dossier bearbeiten", + "upload-document": "Dokument hochgeladen", + "assign": "Besitzer und Mitglieder zuweisen", + "delete": "Dossier löschen", + "download-redacted-files": "Geschwärzte Dateien herunterladen" + }, + "new-rule": { + "toast": { + "actions": { + "reanalyse-all": "Alle analysieren", + "later": "Später", + "reanalyse-file": "Diese Datei analysieren" + }, + "message-dossier": "Reanalyse nötig:" + }, + "label": "Veraltet" + }, + "no-data": { + "action": "Dokument hochladen", + "title": "Noch gibt es keine Dokumente." + }, + "no-match": { + "title": "Die ausgewählten Filter treffen auf kein Dokument zu." + }, + "ocr-file": "OCR-Dokument", + "ocr-performed": "Diese Datei wurde mithilfe von OCR konvertiert.", + "open-document": "Dokument öffnen", + "quick-filters": { + "assigned-to-me": "Mir zuweisen", + "assigned-to-others": "Anderen zugewiesen", + "recent": "Neu ({hours} h)", + "unassigned": "Niemandem zugewiesen" + }, + "reanalyse-dossier": { + "error": "Die Dateien konnten nicht für eine Reanalyse eingeplant werden. Bitte versuchen Sie es erneut.", + "success": "Dateien für Reanalyse vorgesehen." + }, + "reanalyse": { + "action": "Datei analysieren" + }, "table-col-names": { "added-on": "Hinzugefügt", "assigned-to": "Zugewiesen an", "name": "Name", - "needs-work": "Arbeitsbelastung", + "needs-work": "Arbeitsvorrat", "pages": "Seiten", "status": "Status" }, "table-header": { - "title": "{length} Dokumente" + "title": "{length} {length, plural, one{document} other{documents}}", + "bulk-select": "Auswahl umkehren" }, "under-approval": "Zur Genehmigung", - "under-review": "Wird überprüft", - "upload-files": "Ziehen" + "under-review": "In Review", + "upload-files": "Sie können Dateien überall per Drag and Drop platzieren...", + "delete-file-error": "Die Datei {{filename}} konnte nicht gelöscht werden", + "delete-files-error": "Die Dateien konnten nicht gelöscht werden.", + "header": "Dossier-Überblick", + "no-ocr": "Kein OCR", + "report": { + "action": "Bericht zur Schwärzung herunterladen" + }, + "search": "Name des Dokuments ...", + "upload-error": "Folgende Datei konnte nicht hochgeladen werden: {{name}}", + "upload-files-btn": "Dateien hochladen" }, - "dossier-templates": "Dossiervorlagen", + "dossier-templates": "Dossier-Vorlagen", "dossier-templates-listing": { "action": { - "delete": "Vorlage löschen", + "delete": "Dossier-Vorlage", "edit": "Vorlage bearbeiten" }, - "add-new": "Neue Dossiervorlage", + "add-new": "Neue Dossier-Vorlage", "bulk": { - "delete": "" + "delete": "Ausgewählte Dossier-Vorlagen löschen" + }, + "dictionaries": "{length} {length, plural, one{dictionary} other{dictionaries}}", + "error": { + "conflict": "Dieses DossierTemplate kann nicht gelöscht werden! Zumindest auf Dossier wird diese Vorlage verwendet!", + "generic": "Dieses DossierTemplate kann nicht gelöscht werden!" }, - "dictionaries": "{length} Wörterbücher", "no-data": { - "title": "Es gibt noch keine Dossiervorlagen." + "title": "Es gibt noch keine Dossier-Vorlagen." }, "no-match": { - "title": "Keine Dossiervorlagen stimmen mit Ihren aktuellen Filtern überein." + "title": "Die ausgewählten Filter treffen auf keine Dossier-Vorlage zu." }, - "search": "Suche...", + "search": "Suchen ...", "table-col-names": { "created-by": "Erstellt von", "created-on": "Erstellt am", @@ -708,26 +845,43 @@ "name": "Name" }, "table-header": { - "title": "{length} Dossiervorlagen" + "title": "{length} {length, plural, one{Dossier-Vorlage} other{Dossier-Vorlagen}}" + }, + "entries": "{{length}} Einträge" + }, + "download-includes": "Wählen Sie die Dokumente für Ihr Download-Paket aus", + "download-status": { + "queued": "Ihr Download wurde zur Warteschlange hinzugefügt. Hier finden Sie alle angeforderten Downloads: My Downloads.", + "dialog": { + "actions": { + "cancel": "Download abbrechen", + "download": "Jetzt herunterladen" + }, + "tooltip": "{{len}} Dateien" + }, + "error": { + "generic": "Fehler beim Herunterladen" } }, - "download-includes": "Wählen Sie aus, was beim Download enthalten ist:", - "download-status": { - "queued": "Ihr Download wurde in die Warteschlange gestellt. Alle angeforderten Downloads finden Sie hier: Meine Downloads ." - }, "download-type": { - "annotated": "", - "flatten": "", - "label": "{length} Dokumentversionen", - "original": "", - "preview": "", - "redacted": "" + "annotated": "PDF mit Anmerkungen", + "flatten": "PDF verflachen", + "label": "{length} Dokumenten{length, plural, one{version} other{versionen}}", + "original": "Optimiertes PDF", + "preview": "PDF-Vorschau", + "redacted": "geschwärztes PDF", + "ORIGINAL": "Optimiertes PDF", + "PREVIEW": "Vorschau-PDF", + "REDACTED": "Geschwärztes PDF" }, "downloads-list": { "actions": { "delete": "Löschen", "download": "Herunterladen" }, + "bulk": { + "delete": "Ausgewählte Downloads löschen" + }, "no-data": { "title": "Keine aktiven Downloads." }, @@ -735,10 +889,11 @@ "date": "Datum", "name": "Name", "size": "Größe", - "status": "Status" + "status": "Status", + "type": "Typ" }, "table-header": { - "title": "{length} Downloads" + "title": "{length} {length, plural, one{download} other{downloads}}" } }, "edit-color-dialog": { @@ -747,337 +902,433 @@ "color": "Farbe", "color-placeholder": "Farbe" }, - "save": "speichern", - "success": "Die Farbe für {color} wurde erfolgreich aktualisiert." + "save": "Speichern", + "success": "Farbe erfolgreich aktualisiert auf {color}." }, "edit-dossier-dialog": { "actions": { - "revert": "", - "save": "" + "revert": "Rückgängig machen", + "save": "Änderungen speichern", + "save-and-close": "Speichern" }, "attributes": { - "custom-attributes": "", - "delete-image": "", - "image-attributes": "", - "no-custom-attributes": "", - "no-image-attributes": "", - "upload-image": "" + "custom-attributes": "Benutzerdefinierte Dossier-Attribute", + "delete-image": "Bild löschen", + "image-attributes": "Bild-Attribute", + "no-custom-attributes": "Es sind keine Text-Attribute vorhanden", + "no-image-attributes": "Es sind keine Bild-Attribute vorhanden", + "upload-image": "Bild hochladen" + }, + "change-successful": "Dossier wurde aktualisiert.", + "delete-successful": "Dossier wurde gelöscht.", + "deleted-documents": { + "action": { + "delete": "Endgültig löschen", + "restore": "Wiederherstellen" + }, + "bulk": { + "delete": "Ausgewählte Dokumente endgültig löschen", + "restore": "Ausgewählte Dokumente wiederherstellen" + }, + "instructions": "Gelöschte Objekte können bis zu {hours} Stunden nach ihrer Löschung wiederhergestellt werden", + "no-data": { + "title": "Es sind keine gelöschten Dokumente vorhanden." + }, + "table-col-names": { + "deleted-on": "Gelöscht am", + "name": "Name", + "pages": "Seiten", + "time-to-restore": "Verbleibende Zeit für Wiederherstellung" + }, + "table-header": { + "label": "{length} {length, plural, one{gelöschtes Dokument} other{gelöschte Dokumente}}" + } }, - "change-successful": "", - "delete-successful": "", "dictionary": { - "entries": "" + "display-name": { + "cancel": "Abbrechen", + "edit": "Anzeigenamen bearbeiten", + "placeholder": "Anzeigenamen eingeben", + "save": "Anzeigenamen speichern" + }, + "entries": "{length} {length, plural, one{entry} other{entries}}" }, "general-info": { "form": { "description": { - "label": "", - "placeholder": "" + "label": "Beschreibung", + "placeholder": "Beschreibung eingeben" }, - "due-date": "", + "due-date": "Termin", "name": { - "label": "", - "placeholder": "" + "label": "Dossier-Name", + "placeholder": "Namen eingeben" }, - "template": "", - "watermark": "" + "template": "Dossier-Vorlage", + "watermark": "Geschwärzte Dokumente mit Wasserzeichen versehen" } }, - "header": "", + "header": "{dossierName} bearbeiten", "nav-items": { - "choose-download": "", - "dictionary": "", - "dossier-attributes": "", - "dossier-dictionary": "", - "dossier-info": "", - "download-package": "", - "general-info": "", - "members": "", - "team-members": "" + "choose-download": "Wählen Sie die Dokumente für Ihr Download-Paket aus:", + "deleted-documents": "Gelöschte Dokumente", + "dictionary": "Wörterbuch", + "dossier-attributes": "Dossier-Attribute", + "dossier-dictionary": "Dossier-Wörterbuch", + "dossier-info": "Dossier-Info", + "download-package": "Download-Paket", + "general-info": "Allgemeine Informationen", + "members": "Mitglieder", + "team-members": "Team-Mitglieder", + "report-attributes": "Bericht-Attribute" }, - "side-nav-title": "", - "unsaved-changes": "" + "side-nav-title": "Konfiguration", + "unsaved-changes": "Sie haben nicht gespeicherte Änderungen. Speichern Sie oder machen Sie die Änderungen rückgängig, bevor Sie die Registerkarte wechseln." }, + "error": { + "close": "Nah dran", + "http": { + "generic": "Aktion mit Code {status} fehlgeschlagen" + }, + "offline": "Du bist offline", + "reload": "Neu laden", + "title": "Hoppla! Etwas ist schief gelaufen...", + "generic": "Okt." + }, + "exact-date": "{day} {month} {year} um {hour}:{minute} Uhr", + "file": "Datei", "file-attribute-types": { - "date": "", - "number": "", - "text": "" + "date": "Datum", + "number": "Nummer", + "text": "Freier Text", + "DATE": "Datum", + "NUMBER": "Anzahl", + "TEXT": "Text" }, - "file-attributes": "Dateiattribute", + "file-attributes": "Datei-Attribute", "file-attributes-csv-import": { "action": { - "cancel-edit-name": "Stornieren", + "cancel-edit-name": "Abbrechen", "edit-name": "Namen bearbeiten", "remove": "Entfernen", - "save-name": "speichern" + "save-name": "Speichern" }, "available": "{value} verfügbar", - "cancel": "Stornieren", + "cancel": "Abbrechen", "csv-column": "CSV-Spalte", "delimiter": "Trennzeichen", "delimiter-placeholder": ",", - "encoding": "Codierung", + "encoding": "Wird verschlüsselt", "encoding-placeholder": "UTF-8", "file": "Datei:", "key-column": "Schlüsselspalte", "key-column-placeholder": "Spalte auswählen ...", "no-data": { - "title": "Keine Dateiattribute definiert. Wählen Sie im linken Bereich eine Spalte aus, um mit der Definition der Dateiattribute zu beginnen." + "title": "Keine Datei-Attribute definiert. Wählen Sie links eine Spalte aus, um Datei-Attribute zu definieren." }, - "no-hovered-column": "Zeigen Sie eine Vorschau der CSV-Spalte an, indem Sie den Mauszeiger über den Eintrag bewegen.", + "no-hovered-column": "Fahren Sie mit der Maus über den Eintrag, um eine Vorschau der CSV-Spalte zu sehen.", "no-sample-data-for": "Keine Beispieldaten für {column}.", - "parse-csv": "Analysieren Sie CSV mit neuen Optionen", + "parse-csv": "CSV-Datei mit neuen Optionen parsen", "quick-activation": { "all": "Alle", - "none": "Keiner" + "none": "Keine" }, "save": { - "error": "Fehler beim Erstellen der Dateiattribute!", + "error": "Fehler beim Erstellen der Datei-Attribute!", "label": "Attribute speichern", - "success": "{count} Dateiattribute erfolgreich erstellt!" + "success": "{count} Datei-{count, plural, one{Attribut} other{Attribute}} erfolgreich erstellt!" }, "search": { - "placeholder": "Suche nach Spaltennamen ..." + "placeholder": "Nach Spaltennamen suchen ..." }, "selected": "{value} ausgewählt", "table-col-names": { "name": "Name", - "primary": "primär", - "primary-info-tooltip": "Der Wert des als primär eingestellten Attributs wird unter dem Dateinamen in der Dokumentenliste angezeigt.", + "primary": "Primärattribut", + "primary-info-tooltip": "Der Wert des Attributs, das als Primärattribut ausgewählt wurde, wird in der Dokumentenliste unter dem Dateinamen angezeigt.", "read-only": "Schreibgeschützt", - "type": "Art" + "type": "Typ" }, "table-header": { "actions": { - "disable-read-only": "Deaktivieren Sie Schreibgeschützt für alle Attribute", - "enable-read-only": "Aktivieren Sie Schreibgeschützt für alle Attribute", - "read-only": "Nur schreibgeschützt machen", + "disable-read-only": "Schreibschutz für alle Attribute aufheben", + "enable-read-only": "Schreibschutz für alle Attribute aktivieren", + "read-only": "Schreibschutz aktivieren", "remove-selected": "Ausgewählte entfernen", - "type": "Art" + "type": "Typ" }, - "title": "{length} Dateiattribute" + "title": "{length} Datei-{length, plural, one{Attribut} other{Attribute}}" }, - "title": "Wählen Sie CSV-Spalten aus, die als Dateiattribute verwendet werden sollen", - "total-rows": "{rows} Zeilen insgesamt" + "title": "CSV-Spalten auswählen, die als Datei-Attribute verwendet werden sollen", + "total-rows": "{rows} Zeilen insgesamt", + "csv-column-preview": "CSV-Spaltenvorschau" }, "file-attributes-listing": { "action": { "delete": "Attribut löschen", - "edit": "Attribut bearbeiten" + "edit": "Attribute bearbeiten" }, - "add-new": "Neues Attribut", + "add-new": "Neue Attribute", "bulk-actions": { "delete": "Ausgewählte Attribute löschen" }, "no-data": { - "title": "Es sind noch keine Dateiattribute vorhanden." + "title": "Es sind noch keine Datei-Attribute vorhanden." }, "no-match": { - "title": "Keine Dateiattribute stimmen mit Ihren aktuellen Filtern überein." + "title": "Die aktuell ausgewählten Filter treffen auf kein Datei-Attribut zu." }, "read-only": "Schreibgeschützt", - "search": "Suche nach Attributnamen ...", + "search": "Nach Attribut-Namen suchen ...", "table-col-names": { "csv-column": "CSV-Spalte", + "displayed-in-file-list": "In Dokumentenliste anzeigen", + "filterable": "Filterbar", "name": "Name", - "primary": "Primär", - "primary-info-tooltip": "Der Wert des als primär eingestellten Attributs wird unter dem Dateinamen in der Dokumentenliste angezeigt.", + "primary": "Primärattribut", + "primary-info-tooltip": "Der Wert des Attributs, das als Primärattribut ausgewählt wurde, wird in der Dokumentenliste unter dem Dateinamen angezeigt.", "read-only": "Schreibgeschützt", "type": "Eingabetyp" }, "table-header": { - "title": "{length} Dateiattribute" + "title": "{length} {length, plural, one{Datei-Attribut} other{Datei-Attribute}}" }, - "upload-csv": "Konfiguration der Dateiattribute hochladen" + "upload-csv": "Datei-Attribute hochladen" }, "file-preview": { - "assign-me": "Weisen Sie mir zu", - "assign-reviewer": "Prüfer zuweisen", - "change-reviewer": "", + "assign-me": "Mir zuweisen", + "assign-reviewer": "Reviewer zuweisen", + "change-reviewer": "Reviewer wechseln", "delta": "Delta", - "delta-tooltip": "Delta View zeigt nur die Änderungen seit der letzten erneuten Analyse an. Diese Ansicht ist nur verfügbar, wenn mindestens eine Änderung vorliegt", - "document-info": "Ihre Dokumenteninfo lebt hier. Dies schließt Metadaten ein, die für jedes Dokument erforderlich sind.", + "delta-tooltip": "Die Delta-Ansicht zeigt nur die Änderungen seit der letzten Reanalyse an. Die Ansicht ist nur verfügbar, wenn es seit der letzten Analyse mindestens 1 Änderung gab", + "document-info": "Dok-Infos: Hier finden Sie die zu Ihrem Dokument hinterlegten Informationen; u. a. die für das Dokument erforderlichen Metadaten.", "download-original-file": "Originaldatei herunterladen", - "exclude-pages": "", - "excluded-from-redaction": "", - "fullscreen": "Vollbild (F)", + "exclude-pages": "Seiten von Schwärzung ausschließen", + "excluded-from-redaction": "Von Schwärzung ausgeschlossen", + "fullscreen": "Vollbildmodus", "last-reviewer": "Zuletzt überprüft von:", "no-data": { - "title": "Auf dieser Seite befinden sich keine Anmerkungen." + "title": "Auf dieser Seite gibt es keine Anmerkungen." }, "quick-nav": { - "jump-first": "Zur ersten Anmerkung springen", - "jump-last": "Zur letzten Anmerkung springen" + "jump-first": "Zur ersten Seite springen", + "jump-last": "Zur letzten Seite springen" }, - "reanalyse-notification": "Dieses Dokument wurde nicht mit dem neuesten Regel- / Wörterbuchsatz verarbeitet. Analysieren Sie jetzt, um aktualisierte Anmerkungen zu erhalten.", + "reanalyse-notification": "Dieses Dokument wurde nicht auf Basis des neuesten Regel-/Wörterbuchsatzes bearbeitet. Analysieren Sie es jetzt, um die Anmerkungen zu analysieren.", "redacted": "Vorschau", - "redacted-tooltip": "Die Redaktionsvorschau zeigt nur Redaktionen an. Betrachten Sie dies als Vorschau für die endgültige redigierte Version. Diese Ansicht ist nur verfügbar, wenn für die Datei keine Änderungen ausstehen", + "redacted-tooltip": "In der Schwärzungsvorschau sehen Sie nur die Schwärzungen. Es handelt sich also um eine Vorschau der endgültigen geschwärzten Version. Diese Ansicht ist nur verfügbar, wenn für die Datei keine Änderungen ausstehen und keine Reanalyse erforderlich ist", "standard": "Standard", - "standard-tooltip": "In der Standard-Workload-Ansicht werden alle Hinweise, Redaktionen und Empfehlungen angezeigt", + "standard-tooltip": "In der Standard-Ansicht des Workloads werden alle Hinweise, Schwärzungen, Empfehlungen und Vorschläge angezeigt. In dieser Ansicht ist die Bearbeitung möglich.", "tabs": { "annotations": { - "jump-to-next": "Zum nächsten springen", - "jump-to-previous": "Zum vorherigen springen", - "label": "Arbeitsbelastung", - "page-is": "", - "select": "Wählen", - "select-all": "", - "select-none": "" + "jump-to-next": "Springe zu Nächster", + "jump-to-previous": "Springe zu Vorheriger", + "label": "Arbeitsvorrat", + "page-is": "Diese Seite ist", + "select": "Auswählen", + "select-all": "Alle", + "select-none": "Keine" }, "document-info": { - "close": "Dokumentinfo schließen", + "close": "Dokumenteninformation schließen", "details": { "created-on": "Erstellt am: {date}", "dossier": "in {dossierName}", - "due": "Geburtstermin", - "pages": "{pages} Seiten" + "due": "Termin: {date}", + "pages": "{pages} Seiten", + "revised-pages": "{{pages}} überprüfte Seiten" }, - "edit": "Dokumentinformationen bearbeiten", - "label": "Dokumentinfo" + "edit": "Infos zum Dokument bearbeiten", + "label": "Infos zum Dokument" }, "exclude-pages": { - "close": "", - "error": "", - "hint": "", - "input-placeholder": "", - "label": "", - "no-excluded": "", - "put-back": "", - "removed-from-redaction": "" + "close": "Schließen", + "error": "Fehler! Seitenauswahl ungültig.", + "hint": "Minus (-) für Bereich und Komma (,) für Aufzählung.", + "input-placeholder": "z. B. 1-20,22,32", + "label": "Seiten ausschließen", + "no-excluded": "Es sind keine Seiten ausgeschlossen.", + "put-back": "Rückgängig machen", + "removed-from-redaction": "Von der Schwärzung ausgeschlossen" }, - "is-excluded": "Die Redaktion ist für dieses Dokument deaktiviert." + "is-excluded": "Schwärzungen für dieses Dokument deaktiviert.", + "quick-navigation": "Schnelle Navigation" }, "toggle-analysis": { - "disable": "Deaktivieren Sie die Redaktion", - "enable": "Zur Redaktion aktivieren", - "only-managers": "Das Aktivieren / Deaktivieren ist nur für Manager zulässig" - } + "disable": "Schwärzen deaktivieren", + "enable": "Schwärzen aktivieren", + "only-managers": "Aktivieren/deaktivieren ist nur Managern gestattet" + }, + "cannot-show-redacted-view": "Schwärzungen nicht synchronisiert. Vorschau der Schwärzungen erst nach Reanalyse verfügbar", + "exit-fullscreen": "Vollbildmodus beenden", + "new-tab-ssr": "Dokument im serverseitigen Rendering-Modus öffnen", + "reanalyse-file": "Datei wird reanalysiert ...", + "reviewer": "Zugewiesen an", + "show-redacted-view": "Preview des geschwärzten Dokuments anzeigen", + "unassigned": "Nicht zugewiesen", + "view-toggle": "Geschwärzte Ansicht" }, "file-status": { - "approved": "", - "error": "", - "excluded": "", - "full-reprocess": "", - "indexing": "", - "ocr-processing": "", - "processing": "", - "reprocess": "", - "unassigned": "", - "under-approval": "", - "under-review": "", - "unprocessed": "" + "approved": "Genehmigt", + "deleted": "Gelöscht", + "error": "Reanalyse erforderlich", + "excluded": "Ausgeschlossen", + "full-reprocess": "Wird analysiert", + "indexing": "Wird analysiert", + "ocr-processing": "OCR-Analyse", + "processing": "Wird analysiert", + "reprocess": "Wird analysiert", + "unassigned": "Nicht zugewiesen", + "under-approval": "In Genehmigung", + "under-review": "In Review", + "unprocessed": "Unbearbeitet" }, "filter-menu": { "filter-options": "Filteroptionen", - "filter-types": "Filtertypen", + "filter-types": "Filter", "label": "Filter", - "with-comments": "Nur Anmerkungen mit Kommentaren anzeigen", - "with-reason-changes": "" + "with-comments": "Nur Anmerkungen mit Kommentaren", + "with-reason-changes": "Nur Schwärzungen, deren Begründungen geändert wurden" }, "filter": { "analysis": "Analyse erforderlich", - "hint": "Nur Hinweise", + "comment": "Kommentare", + "hint": "Nut Hinweise", "image": "Bilder", "none": "Keine Anmerkungen", - "redaction": "Redigiert", - "suggestion": "Vorgeschlagene Redaktion", + "redaction": "Geschwärzt", + "suggestion": "Vorgeschlagene Schwärzung", "updated": "Aktualisiert" }, "filters": { - "assigned-people": "Beauftragter", + "assigned-people": "Beauftragt", "dossier-templates": "Regelsätze", + "empty": "Leer", "filter-by": "Filter:", - "needs-work": "Arbeitsbelastung", - "people": "Dossiermitglied (e)", - "status": "Status" + "needs-work": "Arbeitsvorrat", + "people": "Dossier-Mitglied(er)", + "status": "Status", + "created-on": "Erstellt am", + "document": "Dokument", + "dossier": "Dossier", + "due-date": "Termin" }, "general-config-screen": { "actions": { - "save": "Konfigurationen speichern", - "test-connection": "Testverbindung" + "save": "Einstellungen speichern", + "test-connection": "Verbindung testen" }, "app-name": { - "label": "", - "placeholder": "" + "label": "Name der Applikation", + "placeholder": "RedactManager" }, "form": { - "auth": "Aktivieren Sie die Authentifizierung", - "change-credentials": "Anmeldeinformationen ändern", - "envelope-from": "Umschlag von", - "envelope-from-hint": "Infotext zum Umschlag aus dem Feld.", - "envelope-from-placeholder": "E-Mail-Adresse des Absenderumschlags", + "auth": "Authentifizierung aktivieren", + "change-credentials": "Zugangsdaten ändern", + "envelope-from": "Ausgangsadresse", + "envelope-from-hint": "Infotext zum Feld „Ausgangsadresse“.", + "envelope-from-placeholder": "Ausgangsadresse", "from": "Von", - "from-display-name": "Name für Absender", - "from-display-name-hint": "Infotext zum Namen des Absenders.", - "from-display-name-placeholder": "Anzeigename für die Absender-E-Mail-Adresse", - "from-placeholder": "Absender-E-Mail-Adresse", - "host": "Gastgeber", + "from-display-name": "Antworten an", + "from-display-name-hint": "Info-Text zum Absendernamen.", + "from-display-name-placeholder": "Anzeigename zur Ausgangsadresse", + "from-placeholder": "E-Mail-Adresse des Absenders", + "host": "Host", "host-placeholder": "SMTP-Host", - "port": "Hafen", - "reply-to": "Antwort an", - "reply-to-display-name": "Name für die Antwort an", - "reply-to-display-name-placeholder": "Anzeigename für die Antwort auf die E-Mail-Adresse", - "reply-to-placeholder": "Antwort an E-Mail-Adresse", - "ssl": "Aktivieren Sie SSL", - "starttls": "Aktivieren Sie StartTLS" + "port": "Port", + "reply-to": "Antwortadresse", + "reply-to-display-name": "Name für Antwortadresse", + "reply-to-display-name-placeholder": "Anzeigename zu Antwort-E-Mail", + "reply-to-placeholder": "Antwort-E-Mail", + "ssl": "SSL aktivieren", + "starttls": "StartTLS aktivieren" }, "general": { "form": { - "forgot-password": "" + "forgot-password": "„Passwort vergessen?“-Link auf der Login-Seite anzeigen" }, - "subtitle": " ", - "title": "" + "subtitle": "", + "title": "Allgemeine Einstellungen" }, - "subtitle": "Mit SMTP (Simple Mail Transfer Protocol) können Sie Ihre E-Mails über die angegebenen Servereinstellungen senden.", + "subtitle": "SMTP (Simple Mail Transfer Protocol) ermöglicht es Ihnen, Ihre E-Mails über die angegebenen Servereinstellungen zu versenden.", "test": { - "error": "Test-E-Mail konnte nicht gesendet werden! Bitte überarbeiten Sie die E-Mail-Adresse.", - "success": "Test-E-Mail wurde erfolgreich gesendet!" + "error": "Die Test-E-Mail konnte nicht gesendet werden! Bitte überprüfen Sie die E-Mail-Adresse.", + "success": "Die Test-E-Mail wurde erfolgreich versendet!" }, - "title": "Konfigurieren Sie das SMTP-Konto" + "title": "SMTP-Konto konfigurieren" + }, + "help-mode": { + "button-text": "Hilfe-Modus (H)", + "clicking-anywhere-on": "Klicken Sie auf eine beliebige Stelle des Bildschirms um zu sehen, welche Bereiche interaktiv sind. Wenn Sie mit der Maus über einen interaktiven Bereich fahren, verändert sich der Mauszeiger, um Ihnen zu zeigen, ob ein Element interaktiv ist.", + "instructions": "Hilfe-Modus-Anleitungen öffnen", + "text": "Hilfe-Modus", + "welcome-to-help-mode": " Willkommen im Hilfe-Modus!
Klicken Sie auf interaktive Elemente, um in einem neuen Tab Infos dazu zu erhalten.
" }, "hint": "Hinweis", "image-category": { - "formula": "", - "image": "", - "logo": "", - "signature": "" + "formula": "Formel", + "image": "Bild", + "logo": "Logo", + "signature": "Signatur" }, "initials-avatar": { - "unassigned": "Nicht zugewiesen", + "unassigned": "Unbekannt", "you": "Sie" }, + "justifications": "Begründungen", + "justifications-listing": { + "actions": { + "delete": "Begründung löschen", + "edit": "Begründung bearbeiten" + }, + "add-new": "Neue Begründung hinzufügen", + "bulk": { + "delete": "Ausgewählte Begründungen löschen" + }, + "no-data": { + "title": "Es gibt noch keine Begründungen." + }, + "table-col-names": { + "description": "Beschreibung", + "name": "Name", + "reason": "Rechtliche Grundlage" + }, + "table-header": "{Länge} {Länge, Plural, eine{Begründung} andere{Begründung}}" + }, "license-info-screen": { "analyzed-pages": "Analysierte Seiten", - "backend-version": "Backend-Anwendungsversion", + "backend-version": "Backend-Version der Anwendung", "chart": { - "cumulative": "Kumulative Seiten", + "cumulative": "Seiten insgesamt", "legend": "Legende", - "licensed-total": "Lizenzierte Summe", + "licensed-total": "Insgesamt lizensiert", "pages-per-month": "Seiten pro Monat", - "total-pages": "Alle Seiten" + "total-pages": "Gesamtzahl der Seiten" }, - "copyright-claim-text": "Copyright © 2020 - {currentYear} knecon AG (unterstützt von IQSER)", - "copyright-claim-title": "Urheberrechtsanspruch", - "current-analyzed": "Analysierte Seiten im aktuellen Lizenzierungszeitraum", - "custom-app-title": "Titel der benutzerdefinierten Anwendung", + "copyright-claim-text": "Copyright © 2020 - {currentYear} knecon AG (powered by IQSER)", + "copyright-claim-title": "Copyright", + "current-analyzed": "In aktuellem Lizenzzeitraum analysierte Seiten", + "custom-app-title": "Name der Anwendung", "email-report": "E-Mail-Bericht", "email": { "body": { - "analyzed": "Insgesamt analysierte Seiten im aktuellen Lizenzzeitraum: {pages}.", + "analyzed": "Im aktuellen Lizenzzeitraum insgesamt analysierte Seiten: {pages}.", "licensed": "Lizenzierte Seiten: {pages}." }, "title": "Lizenzbericht {licenseCustomer}" }, - "end-user-license-text": "Die Verwendung dieses Produkts unterliegt den Bestimmungen der Redaction End User Agreement, sofern nicht anders angegeben.", + "end-user-license-text": "Die Nutzung dieses Produkts unterliegt den Bedingungen der Endbenutzer-Lizenzvereinbarung für den RedactManager, sofern darin nichts anderweitig festgelegt.", "end-user-license-title": "Endbenutzer-Lizenzvereinbarung", - "frontend-version": "Frontend-Anwendungsversion", "licensed-page-count": "Anzahl der lizenzierten Seiten", - "licensed-to": "Lizenziert an", + "licensed-to": "Lizenziert für", "licensing-details": "Lizenzdetails", - "licensing-period": "Lizenzzeitraum", - "total-analyzed": "Insgesamt analysierte Seiten seit {date}", - "unlicensed-analyzed": "Nicht lizenzierte analysierte Seiten", - "usage-details": "Verwendungsdetails" + "licensing-period": "Laufzeit der Lizenz", + "ocr-analyzed-pages": "Mit OCR konvertierte Seiten", + "total-analyzed": "Seit {date} insgesamt analysierte Seiten", + "unlicensed-analyzed": "Über Lizenz hinaus analysierte Seiten", + "usage-details": "Nutzungsdetails", + "3rd-party-title": "Hinweis auf Lizenzen von Drittanbietern", + "frontend-version": "Frontend-Anwendungsversion" }, "license-information": "Lizenzinformationen", "manual-annotation": { @@ -1088,176 +1339,269 @@ "content": { "comment": "Kommentar", "dictionary": "Wörterbuch", - "legalBasis": "Rechtliche Grundlage", - "reason": "Grund", - "reason-placeholder": "Wähle einen Grund ...", - "rectangle": "Benutzerdefiniertes Rechteck", + "legalBasis": "Rechtsgrundlage", + "reason": "Begründung", + "reason-placeholder": "Wählen Sie eine Begründung aus ...", + "rectangle": "Benutzerdefinierter Bereich", "text": "Ausgewählter Text:" }, "header": { "dictionary": "Zum Wörterbuch hinzufügen", - "false-positive": "Falsch positiv setzen", - "force": "Redaktion erzwingen", - "redaction": "Redaktion", - "request-dictionary": "Anfrage zum Wörterbuch hinzufügen", - "request-false-positive": "Falsch positiv anfordern", - "request-redaction": "Redaktion anfordern" + "false-positive": "Als Falsch-Positiv definieren", + "force": "Schwärzung erzwingen", + "redaction": "Schwärzung", + "request-dictionary": "Neuen Wörterbucheintrag vorschlagen", + "request-false-positive": "Als Falsch-Positiv vorschlagen", + "request-redaction": "Schwärzung vorschlagen" + }, + "add-redaction": { + "failed": "Fehler beim Hinzufügen der Schwärzung: {{message}}", + "success": "Vorschlag für Schwärzung wurde hinzugefügt!" } + }, + "approve-request": { + "error": "Genehmigen des Vorschlags fehlgeschlagen.", + "success": "Vorschlag genehmigt." + }, + "redaction-add": { + "error": "Hinzufügen der Schwärzung fehlgeschlagen.", + "success": "Schwärzung hinzugefügt." + }, + "redaction-request": { + "error": "Vorschlagen der Schwärzung fehlgeschlagen.", + "success": "Schwärzung vorgeschlagen." + }, + "remove-redaction-request": { + "error": "Entfernen der Schwärzung fehlgeschlagen.", + "success": "Schwärzung wurde entfernt." + }, + "undo": { + "error": "Die Aktion konnte nicht rückgängig gemacht werden.", + "success": "Aktion rückgängig gemacht." } }, + "months": { + "apr": "Apr.", + "aug": "August", + "dec": "Dez.", + "feb": "Feb.", + "jan": "Jan.", + "jul": "Jul.", + "jun": "März", + "mar": "März", + "may": "Nov.", + "nov": "Nov.", + "oct": "Okt.", + "sep": "Sept." + }, + "notification": { + "assign-approver": "Sie wurden dem Dokument {fileName} im Dossier {dossierName} als Genehmiger zugewiesen!", + "assign-reviewer": "Sie wurden dem Dokument {fileName} im Dossier {dossierName} als Reviewer zugewiesen!", + "document-approved": "{fileName} wurde genehmigt!", + "dossier-deleted": "Dossier: {dossierName} wurde gelöscht!", + "dossier-owner-deleted": "Der Dossier-Owner von {dossierName} wurde entfernt!", + "dossier-owner-removed": "Der Dossier-Owner von {dossierName} wurde entfernt!", + "dossier-owner-set": "Eigentümer von {dossierName} geändert zu {user}!", + "unassigned-from-file": "Sie wurden vom Dokument {fileName} im Dossier {dossierName} entfernt!", + "user-becomes-dossier-member": "{user} ist jetzt Mitglied des Dossiers {dossierName}!", + "user-demoted-to-reviewer": "{user} wurde im Dossier {dossierName} auf die Reviewer-Berechtigung heruntergestuft!", + "user-promoted-to-approver": "{user} wurde im Dossier {dossierName} zum Genehmiger ernannt!", + "user-removed-as-dossier-member": "{user} wurde als Mitglied von: {dossierName} entfernt!" + }, "notifications": { - "mark-as": "als {type, select, read{gelesen} unread{ungelesen} other{}} markieren" + "mark-as": "Als {type, select, read{gelesen} unread{ungelesen} other{}} markieren", + "no-data": "Sie haben keine Benachrichtigungen.", + "today": "Heute", + "tomorrow": "Morgen", + "yesterday": "Gestern" }, "overwrite-files-dialog": { "options": { "cancel": "Alle Uploads abbrechen", - "overwrite": "Ersetzen Sie das vorhandene Dokument", - "remember": "Erinnere dich an die Wahl und frag mich nicht noch einmal", + "overwrite": "Vorhandenes Dokument ersetzen", + "remember": "Auswahl speichern und nicht noch einmal fragen", "skip": "Vorhandenes Dokument behalten" }, - "question": "{filename} existiert bereits. Wählen Sie, wie Sie fortfahren möchten:", - "title": "Dokument existiert bereits!" + "question": "{filename} ist bereits vorhanden. Wie möchten Sie fortfahren?", + "title": "Das Dokument existiert bereits!" }, "page": "Seite", "pagination": { - "next": "Nächster", - "previous": "Zurück" + "next": "Nächste", + "previous": "Vorherige" }, "pdf-viewer": { "text-popup": { "actions": { - "search": "Suche nach Auswahl" + "search": "Nach Auswahl suchen" } - } + }, + "search-in-progress": "Suche läuft ..." }, - "pending-changes-guard": "WARNUNG: Sie haben nicht gespeicherte Änderungen. Drücken Sie Abbrechen, um zurück zu gehen und diese Änderungen zu speichern, oder OK, um diese Änderungen zu verlieren.", - "readonly": "Schreibgeschützt", + "pending-changes-guard": "ACHTUNG: Sie haben ungespeicherte Änderungen. Klicken Sie auf „Abbrechen“, wenn Sie zurückkehren und die Änderungen speichern möchten. Klicken Sie auf „OK“, um die Änderungen zu speichern.", + "readonly": "Lesemodus", "recategorize-image-dialog": { "actions": { - "cancel": "", - "save": "" + "cancel": "Abbrechen", + "save": "Änderungen speichern" }, "content": { - "comment": "", - "type": "", - "type-placeholder": "" + "comment": "Kommentar", + "type": "Ausgewählter Bildtyp", + "type-placeholder": "Einen Typ auswählen ..." }, - "header": "" + "header": "Bildtypen bearbeiten" }, - "redaction": "Redaktion", + "redaction": "Schwärzung", "remove-annotations-dialog": { - "confirm": "Ja, fortfahren und entfernen!", - "cancel": "Stornieren", + "cancel": "Abbrechen", + "confirm": "Ja, fortfahren und löschen!", "dictionary": "Wörterbuch", - "image-type": "", + "image-type": "Bild: {typeLabel}", "remove-from-dictionary": { - "question": "Folgende Einträge werden aus ihren jeweiligen Wörterbüchern entfernt:", - "title": "Aus dem Wörterbuch entfernen" + "question": "Folgende Einträge werden aus den jeweiligen Wörterbüchern gelöscht:", + "title": "Aus dem Wörterbuch löschen" }, "remove-only-here": { - "question": "Folgende Redaktionen werden nur hier entfernt:", - "title": "Redaktion entfernen" + "question": "Folgende Schwärzungen werden nur hier entfernt:", + "title": "Schwärzung entfernen" }, - "value": "Wert" + "value": "Wert", + "deny": "Abbrechen" }, "report-type": { - "label": "{length} Berichtstypen" + "label": "{length} {length, plural, one{Berichtstyp} other{Berichtstypen}}", + "EXCEL_MULTI_FILE": "Excel (für alle Dateien)", + "EXCEL_SINGLE_FILE": "Excel (für jede Datei)", + "WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE": "Justification Appendix A1", + "WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE": "Justification Appendix A2" }, - "reports": "", + "reports": "Berichte", "reports-screen": { - "description": "", - "document-setup-description": "", - "document-setup-heading": "", - "report-documents": "", - "title": "", - "upload-document": "" + "description": "Ein kurzer Text, der erläutert, was Platzhalter sind und wie Sie sie in Ihrer Berichtsvorlage einsetzen können. Es ist bekannt, dass ein Leser vom lesbaren Inhalt einer Seite abgelenkt wird, wenn er sich das Layout ansieht.", + "descriptions": { + "dossier-attributes": "Dieser Platzhalter wird durch den Wert des Dossier-Attributs {attribute} ersetzt.", + "file-attributes": "Dieser Platzhalter wird durch den Wert des Dateiattributs {attribute} ersetzt.", + "general": { + "date": { + "d-m-y": "Dieser Platzhalter wird durch das Erstellungsdatum des Berichts in der üblichen Tag-Monat-Jahr-Notation (TT.MM.JJJJ) ersetzt, zB 15.10.2021.", + "m-d-y": "Dieser Platzhalter wird durch das Erstellungsdatum des Berichts im amerikanischen rein numerischen Datumsformat (MM/dd/yyyy) ersetzt, zB 15.10.2021.", + "y-m-d": "Dieser Platzhalter wird durch das Erstellungsdatum des Berichts im internationalen ISO 8601-Format (yyyy-MM-dd) ersetzt, zB 2021-10-15." + }, + "dossier": { + "name": "Dieser Platzhalter wird durch den Namen des Dossiers ersetzt, in dem die geschwärzten Dateien gespeichert sind." + }, + "file": { + "name": "Dieser Platzhalter wird durch den Dateinamen ersetzt." + }, + "redaction": { + "excerpt": "Dieser Platzhalter wird durch einen Textausschnitt ersetzt, der die Schwärzung enthält.", + "justification": "Dieser Platzhalter wird durch die Begründung der Schwärzung ersetzt. Es ist eine Kombination aus dem Rechtsverweis (justificationParagraph) und dem Begründungstext (justificationReason).", + "justification-paragraph": "Dieser Platzhalter wird durch den Rechtshinweis der Begründung der Redaktion ersetzt.", + "justification-reason": "Dieser Platzhalter wird durch den Begründungstext der Schwärzung ersetzt.", + "page": "Dieser Platzhalter wird durch die Seitenzahl der Redaktion ersetzt.", + "paragraph": "Dieser Platzhalter wird durch den Absatz ersetzt, der die Schwärzung enthält." + }, + "time": { + "h-m": "Dieser Platzhalter wird durch den Zeitpunkt ersetzt, zu dem der Bericht erstellt wurde." + } + } + }, + "document-setup-description": "Ein kurzer Text, der erläutert, was Platzhalter sind und wie Sie sie in Ihrer Berichtsvorlage einsetzen können. Es ist bekannt, dass ein Leser vom lesbaren Inhalt einer Seite abgelenkt wird, wenn er sich das Layout ansieht.", + "document-setup-heading": "Dokumenten-Konfiguration", + "invalid-upload": "Ungültiges Upload-Format ausgewählt! Unterstützt werden Dokumente im .xlsx- und im .docx-Format", + "multi-file-report": "(Mehrere Dateien)", + "report-documents": "Dokumente für den Bericht", + "table-header": { + "description": "Beschreibung", + "placeholders": "Platzhalter" + }, + "title": "Berichte", + "upload-document": "Ein Dokument hochladen" }, - "reset-filters": "Filter zurücksetzen", + "reset-filters": "Zurücksetzen", "reset-password-dialog": { "actions": { - "cancel": "", - "save": "" + "cancel": "Abbrechen", + "save": "Speichern" }, "form": { - "password": "" + "password": "Temporäres Passwort" }, - "header": "" + "header": "Temporäres Passwort für {userName} festlegen" }, "roles": { - "inactive": "", - "manager-admin": "", - "no-role": "", - "red-admin": "", - "red-manager": "", - "red-user": "", - "red-user-admin": "", - "regular": "" + "inactive": "Inaktiv", + "manager-admin": "Manager & Admin", + "no-role": "Keine Rolle definiert", + "red-admin": "Anwendungsadministrator", + "red-manager": "Manager", + "red-user": "Benutzer", + "red-user-admin": "Benutzer-Admin", + "regular": "Regulär", + "INACTIVE": "Inaktiv", + "MANAGER_ADMIN": "Manager & Admin", + "NO_ROLE": "Keine Rolle definiert", + "RED_ADMIN": "Anwendungsadministrator", + "RED_MANAGER": "Manager", + "RED_USER": "Benutzer", + "RED_USER_ADMIN": "Benutzer-Admin", + "REGULAR": "Regelmäßig" }, - "rule-editor": "Regeleditor", + "rule-editor": "Regel-Editor", "rules-screen": { "error": { - "generic": "Etwas ist schief gelaufen ... Regelaktualisierung fehlgeschlagen!" + "generic": "Es ist ein Fehler aufgetreten ... Die Regeln konnten nicht aktualisiert werden!" }, - "revert-changes": "Zurückkehren", + "revert-changes": "Anmeldedaten speichern", "save-changes": "Änderungen speichern", "success": { - "generic": "Regeln aktualisiert!" + "generic": "Die Regeln wurden aktualisiert!" + }, + "action": { + "download": "Regeln herunterladen", + "upload": "Upload-Regeln" } }, "search-screen": { "cols": { - "document": "", - "dossier": "", - "pages": "", - "status": "" + "document": "Dokument", + "dossier": "Dossier", + "pages": "Seiten", + "status": "Status" }, "filters": { - "by-dossier": "", - "search-placeholder": "Dossier..." + "by-dossier": "Nach Dossier filtern", + "search-placeholder": "Dossiername..." }, - "missing": "", - "must-contain": "", - "no-data": "", - "table-header": "" + "missing": "Fehlt", + "must-contain": "Muss enthalten", + "no-data": "Geben Sie einen Suchbegriff in die Suchleiste, um nach Dokumenten oder Inhalten von Dokumenten zu suchen.", + "table-header": "{length} {length, plural, one{Suchergebnis} other{Suchergebnisse}}" }, "search": { - "entire-platform": "", - "placeholder": "", - "this-dossier": "" + "entire-platform": "ganze Plattform", + "placeholder": "Nach Dokumenten oder Dokumenteninhalt suchen", + "this-dossier": "in diesem Dossier", + "header-label": "Gesamte Plattform durchsuchen" }, "smtp-auth-config": { "actions": { - "cancel": "Stornieren", - "save": "Anmeldeinformationen speichern" + "cancel": "Abbrechen", + "save": "Anmeldedaten speichern" }, "form": { "password": "Passwort", - "username": "Nutzername", - "username-placeholder": "Login Benutzername" + "username": "Benutzername", + "username-placeholder": "Login-Benutzername" }, - "title": "Aktivieren Sie die Authentifizierung" + "title": "Authentifizierung aktivieren" }, "time": { - "days": "", - "hours": "", - "less-than-an-hour": "", - "no-time-left": "" - }, - "yesterday": "", - "exact-date": "", - "months": { - "jan": "", - "feb": "", - "mar": "", - "apr": "", - "may": "", - "jun": "", - "jul": "", - "aug": "", - "sep": "", - "oct": "", - "nov": "", - "dec": "" + "days": "{days} {days, plural, one{Tag} other{Tage}}", + "hours": "{hours} {hours, plural, one{Stunde} other{Stunden}}", + "less-than-an-hour": "< 1 Stunde", + "no-time-left": "Frist für Wiederherstellung verstrichen" }, "top-bar": { "navigation-items": { @@ -1265,58 +1609,59 @@ "dossiers": "Aktives Dossier", "my-account": { "children": { - "admin": "Die Einstellungen", + "admin": "Einstellungen", "downloads": "Meine Downloads", "language": { - "de": "Deutsche", + "de": "Deutsch", "en": "Englisch", "label": "Sprache" }, - "logout": "Ausloggen", + "logout": "Abmelden", "my-profile": "Mein Profil", - "trash": "" + "trash": "Papierkorb" } } } }, "trash": { "action": { - "delete": "", - "restore": "" + "delete": "Endgültig löschen", + "restore": "Wiederherstellen" }, "bulk": { - "delete": "", - "restore": "" + "delete": "Ausgewählte Dossiert endgültig löschen", + "restore": "Ausgewählte Dossiers wiederherstellen" }, - "label": "", + "label": "Papierkorb", "no-data": { - "title": "" + "title": "Es wurde noch kein Dossier angelegt." }, "no-match": { - "title": "" + "title": "Die ausgewählten Filter treffen auf kein Dossier zu." }, "table-col-names": { - "deleted-on": "", - "name": "", - "owner": "", - "time-to-restore": "" + "deleted-on": "Gelöscht am", + "name": "Name", + "owner": "Eigentümer", + "time-to-restore": "Verbleibende Zeit für Wiederherstellung" }, "table-header": { - "title": "" + "title": "{length} {length, plural, one{gelöschtes Dossier} other{gelöschte Dossiers}}" } }, - "type": "Art", + "type": "Typ", + "unknown": "Unbekannt", "upload-status": { "dialog": { "actions": { "cancel": "Upload abbrechen", - "re-upload": "Wiederholen Sie den Upload" + "re-upload": "Upload erneut versuchen" }, "title": "Datei-Uploads ({len})" }, "error": { - "file-size": "Datei zu groß. Das Limit ist {size} MB.", - "generic": "Datei konnte nicht hochgeladen werden." + "file-size": "Datei zu groß. Die maximal zulässige Größe beträgt {size} MB.", + "generic": "Fehler beim Hochladen des Dokuments" } }, "user-listing": { @@ -1330,27 +1675,27 @@ "delete-disabled": "Sie können Ihr eigenes Konto nicht löschen." }, "no-match": { - "title": "Keine Benutzer stimmen mit Ihren aktuellen Filtern überein." + "title": "Die ausgewählten Filter treffen auf keinen Benutzer zu." }, - "search": "Suche...", + "search": "Suche ...", "table-col-names": { "active": "Aktiv", - "email": "Email", + "email": "E-Mail-Adresse", "name": "Name", "roles": "Rollen" }, "table-header": { - "title": "{length} Benutzer" + "title": "{length} {length, plural, one{user} other{users}}" } }, "user-management": "Benutzerverwaltung", "user-profile": { "actions": { - "change-password": "", + "change-password": "Passwort ändern", "save": "Profil speichern" }, "form": { - "email": "Email", + "email": "E-Mail", "first-name": "Vorname", "last-name": "Nachname" }, @@ -1361,31 +1706,141 @@ "users": "Benutzer im Arbeitsbereich" }, "collapse": "Details ausblenden", - "expand": "Zeige Details", + "expand": "Details anzeigen", "title": "Benutzer" }, + "view-mode": { + "list": "Liste", + "view-as": "Ansicht als:", + "workflow": "Arbeitsablauf" + }, "watermark": "Wasserzeichen", "watermark-screen": { "action": { - "change-success": "Wasserzeichen aktualisiert!", - "delete-success": "Wasserzeichen gelöscht.", - "error": "Wasserzeichen konnte nicht aktualisiert werden", - "revert": "Zurückkehren", + "change-success": "Das Wasserzeichen wurde aktualisiert!", + "delete-success": "Das Wasserzeichen wurde gelöscht.", + "error": "Fehler beim Aktualisieren des Wasserzeichens", + "revert": "Rückgängig machen", "save": "Änderungen speichern" }, "form": { "color": "Farbe", "font-size": "Schriftgröße", "font-type": "Schriftart", - "opacity": "Opazität", - "orientation": "Orientierung", + "opacity": "Deckkraft", + "orientation": "Ausrichtung", "text-placeholder": "Text eingeben" }, "title": "Wasserzeichen" }, - "annotation-engines": { - "dictionary": "", - "ner": "", - "rule": "" - } + "yesterday": "Gestern", + "app-name": "DDA-R", + "APPROVED": "Genehmigt", + "assign-approver-owner": { + "dialog": { + "cancel": "Schließen", + "save": "Speichern", + "single-user": "Genehmiger", + "title": "Genehmiger verwalten" + } + }, + "assign-reviewer-owner": { + "dialog": { + "cancel": "Abbrechen", + "save": "Speichern", + "single-user": "Reviewer", + "title": "Reviewer für Dokument auswählen" + } + }, + "change-legal-basis": "Änderung der Rechtsgrundlage ausstehend", + "comment": "Kommentar", + "dossier-dictionary-dialog": { + "cancel": "abbrechen", + "save-changes": "Änderungen speichern", + "title": "Dossier-Wörterbuch" + }, + "dossier-member-guard": { + "access-denied": "Sie haben keinen Zugriff auf diese Seite." + }, + "efsa": "EFSA-Genehmigung", + "ERROR": "Neuanalyse erforderlich", + "EXCLUDED": "Ausgeschlossen", + "finished": "Beendet", + "FULLREPROCESS": "Wird analysiert", + "group": { + "hints": "Hinweis-Wörterbücher", + "redactions": "Schwärzungs-Wörterbücher" + }, + "OCR_PROCESSING": "OCR-Analyse", + "pending-analysis": "Reanalyse ausstehend", + "PROCESSING": "Wird analysiert", + "report": { + "action": { + "efsa": "Mit EFSA-Vorlage herunterladen", + "label": "Schwärzungsbericht herunterladen", + "syngenta": "Mit Syngenta-Vorlage herunterladen" + }, + "unavailable": "Der Schwärzungsbericht ist erst verfügbar, wenn alle Dateien genehmigt wurden.", + "unavailable-single": "Der Schwärzungsbericht ist erst verfügbar, wenn diese Datei genehmigt wurde." + }, + "REPROCESS": "Wird analysiert", + "settings": "Einstellungen", + "skipped": "Übersprungen", + "smtp-config-screen": { + "actions": { + "save": "Konfiguration speichern", + "test-connection": "Test-Verbindung" + }, + "form": { + "auth": "Authentifizierung aktivieren", + "change-credentials": "Zugangsdaten ändern", + "envelope-from": "Ausgangsadresse", + "envelope-from-hint": "Infotext zum Feld „Ausgangsadresse“.", + "envelope-from-placeholder": "Absender-E-Mail", + "from": "Von", + "from-display-name": "Name für Absender", + "from-display-name-hint": "Infotext zum Namen für den Absender.", + "from-display-name-placeholder": "Anzeigename zu Absender-E-Mail-Adresse", + "from-placeholder": "E-Mail-Adresse des Absenders", + "host": "Host", + "host-placeholder": "SMTP-Host", + "port": "Port", + "reply-to": "Antwortadresse", + "reply-to-display-name": "Name zu Antwortadresse", + "reply-to-display-name-placeholder": "Anzeigename zur Antwort-E-Mail", + "reply-to-placeholder": "E-Mail-Adresse für Antwort", + "ssl": "SSL aktivieren", + "starttls": "StartTLS aktivieren" + }, + "general": { + "form": { + "forgot-password": "„Passwort vergessen“-Link auf der Login-Seite anzeigen" + }, + "title": "Allgemeine Einstellungen" + }, + "subtitle": "SMTP (Simple Mail Transfer Protocol) ermöglicht es Ihnen, Ihre E-Mails über die angegebenen Servereinstellungen zu versenden.", + "test": { + "error": "Die Test-E-Mail konnte nicht gesendet werden! Bitte überprüfen Sie die E-Mail-Adresse.", + "success": "Die Test-E-Mail wurde erfolgreich versendet!" + }, + "title": "SMTP-Konto konfigurieren" + }, + "sorting": { + "alphabetically": "Alphabetisch", + "custom": "Benutzerdefiniert", + "number-of-analyses": "Anzahl der Analysen", + "number-of-pages": "Anzahl der Seiten", + "oldest": "Älteste", + "recent": "Neueste" + }, + "stream-download": { + "abort": "Es läuft gerade ein Download. Wenn Sie dieses Fenster schließen, wird er abgebrochen.", + "error": "Fehler beim Herunterladen der Datei {{filename}}. Bitte versuchen Sie es noch einmal ..." + }, + "submitted": "Gesendet", + "suggestion": "Vorschlag für eine Schwärzung", + "UNASSIGNED": "Nicht zugewiesen", + "UNDER_APPROVAL": "In Genehmigung", + "UNDER_REVIEW": "In Review", + "UNPROCESSED": "Nicht analysiert" } diff --git a/docker/common/nginx/nginx.conf b/docker/common/nginx/nginx.conf index 178d9e7f0..2e591afd5 100644 --- a/docker/common/nginx/nginx.conf +++ b/docker/common/nginx/nginx.conf @@ -1,5 +1,4 @@ server { - listen 8080; proxy_hide_header WWW-Authenticate; port_in_redirect off; @@ -7,6 +6,8 @@ server { root /usr/share/nginx/html; # SSL stuff for cloudflare proxy-ing - ignores SSL certificate and uses SNI + add_header Content-Security-Policy "default-src 'self';"; + proxy_ssl_verify off; proxy_read_timeout 1m; proxy_ssl_server_name on; diff --git a/docker/red-ui/Dockerfile b/docker/red-ui/Dockerfile index b099b8d23..9dd0db290 100644 --- a/docker/red-ui/Dockerfile +++ b/docker/red-ui/Dockerfile @@ -46,5 +46,7 @@ RUN chmod g+r -R /usr/share/nginx/html ## Change permissions to enable openShift functionality RUN chmod -R g+rwx /var/cache/nginx /var/run /var/log/nginx /usr/share /etc/nginx +USER 1001 + COPY docker/red-ui/docker-entrypoint.sh / CMD ["/docker-entrypoint.sh"] diff --git a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts index b26199467..a93bcec16 100644 --- a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts +++ b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts @@ -4,7 +4,7 @@ import { IDictionary } from './dictionary'; export class Dictionary implements IDictionary, IListable { readonly addToDictionaryAction: boolean; readonly caseInsensitive: boolean; - readonly description?: string; + readonly description: string; readonly dossierTemplateId?: string; entries: List; readonly hexColor?: string; @@ -17,7 +17,7 @@ export class Dictionary implements IDictionary, IListable { constructor(dictionary: IDictionary, readonly virtual = false) { this.addToDictionaryAction = !!dictionary.addToDictionaryAction; this.caseInsensitive = !!dictionary.caseInsensitive; - this.description = dictionary.description; + this.description = dictionary.description ?? ''; this.dossierTemplateId = dictionary.dossierTemplateId; this.entries = dictionary.entries ?? []; this.hexColor = dictionary.hexColor; diff --git a/libs/red-domain/src/lib/file-attributes/field.ts b/libs/red-domain/src/lib/file-attributes/field.ts new file mode 100644 index 000000000..52c1d8a94 --- /dev/null +++ b/libs/red-domain/src/lib/file-attributes/field.ts @@ -0,0 +1,11 @@ +import { IListable } from '@iqser/common-ui'; +import { FileAttributeConfigType } from '@red/domain'; + +export interface IField extends IListable { + id: string; + csvColumn: string; + name: string; + type: FileAttributeConfigType; + readonly: boolean; + primaryAttribute: boolean; +} diff --git a/libs/red-domain/src/lib/file-attributes/index.ts b/libs/red-domain/src/lib/file-attributes/index.ts index ee91c20a8..0380a37e4 100644 --- a/libs/red-domain/src/lib/file-attributes/index.ts +++ b/libs/red-domain/src/lib/file-attributes/index.ts @@ -2,3 +2,4 @@ export * from './file-attribute-config'; export * from './file-attribute-config.model'; export * from './file-attributes'; export * from './file-attributes-config'; +export * from './field'; diff --git a/libs/red-domain/src/lib/search/index.ts b/libs/red-domain/src/lib/search/index.ts index 78ecaf160..536d4fccf 100644 --- a/libs/red-domain/src/lib/search/index.ts +++ b/libs/red-domain/src/lib/search/index.ts @@ -2,3 +2,5 @@ export * from './matched-document'; export * from './matched-section'; export * from './search.request'; export * from './search.response'; +export * from './search-list-item'; +export * from './search-input'; diff --git a/libs/red-domain/src/lib/search/search-input.ts b/libs/red-domain/src/lib/search/search-input.ts new file mode 100644 index 000000000..597b6391f --- /dev/null +++ b/libs/red-domain/src/lib/search/search-input.ts @@ -0,0 +1,6 @@ +import { List } from '@iqser/common-ui'; + +export interface ISearchInput { + readonly query: string; + readonly dossierIds?: List; +} diff --git a/libs/red-domain/src/lib/search/search-list-item.ts b/libs/red-domain/src/lib/search/search-list-item.ts new file mode 100644 index 000000000..c1b2b700b --- /dev/null +++ b/libs/red-domain/src/lib/search/search-list-item.ts @@ -0,0 +1,12 @@ +import { IListable, List } from '@iqser/common-ui'; + +export interface ISearchListItem extends IListable { + readonly dossierId: string; + readonly filename: string; + readonly unmatched: List | null; + readonly highlights: Record; + readonly routerLink: string; + readonly status: string; + readonly dossierName: string; + readonly numberOfPages: number; +} diff --git a/package.json b/package.json index 57df2c353..07142674e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redaction", - "version": "2.334.0", + "version": "2.344.0", "private": true, "license": "MIT", "scripts": { @@ -82,6 +82,7 @@ "@types/node": "16.9.1", "@typescript-eslint/eslint-plugin": "4.33.0", "@typescript-eslint/parser": "4.33.0", + "axios": "^0.24.0", "cypress": "^6.9.1", "cypress-file-upload": "^5.0.8", "cypress-keycloak": "^1.7.0", diff --git a/paligo-theme.tar.gz b/paligo-theme.tar.gz index 555f94a8f..8e430de47 100644 Binary files a/paligo-theme.tar.gz and b/paligo-theme.tar.gz differ diff --git a/tools/auto-i18n/README.md b/tools/auto-i18n/README.md deleted file mode 100644 index 9318bba79..000000000 --- a/tools/auto-i18n/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Run Example - -node translate.js ./../../apps/red-ui/src/assets/i18n/en.json de AIzaSyC2fOUHLV6nhmCSwKcacaNqumn20k8Ic_M - -# API KEY - -AIzaSyC2fOUHLV6nhmCSwKcacaNqumn20k8Ic_M diff --git a/tools/auto-i18n/translate.js b/tools/auto-i18n/translate.js deleted file mode 100644 index 7fe53e9db..000000000 --- a/tools/auto-i18n/translate.js +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs'); -const moment = require('moment'); -const _ = require('lodash'); -const path = require('path'); -const agent = require('superagent-promise')(require('superagent'), Promise); -const { translate } = require('google-translate-api-browser'); -let dicc = {}; - -//Lang Codes https://ctrlq.org/code/19899-google-translate-languages - -if (process.argv.length >= 4) { - //Args - const inputFile = process.argv[2]; - const destinationCodes = process.argv[3].split(','); - const apiKey = process.argv.length > 4 && process.argv[4]; - - const apiUrl = _.template('https://www.googleapis.com/language/translate/v2?key=<%= apiKey %>&q=<%= value %>&source=en&target=<%= languageKey %>'); - - const transformResponse = (res) => { - return _.get(JSON.parse(res.text), ['data', 'translations', 0, 'translatedText'], ''); - }; - - const getCache = (languageKey) => { - try { - dicc[languageKey] = {}; - let fileContent = fs.readFileSync(`./translateCache-${languageKey}.txt`, 'utf-8').split('\n'); - fileContent.map((line) => { - let cached = line.split('|'); - if (cached[0]) dicc[languageKey][cached[0]] = cached[1]; - }); - } catch (error) {} - }; - const cachedIndex = (key, value, languageKey) => { - const line = key + '|' + value + '\n'; - dicc[languageKey][key] = value; - fs.appendFileSync(`./translateCache-${languageKey}.txt`, line); - return value; - }; - - function iterLeaves(value, keyChain, accumulator, languageKey) { - accumulator = accumulator || {}; - keyChain = keyChain || []; - if (_.isObject(value)) { - return _.chain(value) - .reduce((handlers, v, k) => { - return handlers.concat(iterLeaves(v, keyChain.concat(k), accumulator, languageKey)); - }, []) - .flattenDeep() - .value(); - } else { - if (typeof value !== 'string') return value; - - return function () { - if (!(value in dicc[languageKey])) { - console.log( - _.template('Translating <%= value %> to <%= languageKey %>')({ - value, - languageKey - }) - ); - - let prom; - //Translates individual string to language code - if (apiKey != '') { - //using apiKey - prom = agent( - 'GET', - apiUrl({ - value: encodeURI(value), - languageKey, - apiKey - }) - ).then(transformResponse); - } else { - //using free api key - prom = translate(value, { to: languageKey }); - } - - return prom - .then((res) => cachedIndex(value, res, languageKey)) - .catch((err) => console.log(err)) - .then((text) => { - //Sets the value in the accumulator - _.set(accumulator, keyChain, text); - - //This needs to be returned to it's eventually written to json - return accumulator; - }); - } else { - console.log(value + ' cached: ' + dicc[languageKey][value]); - _.set(accumulator, keyChain, dicc[languageKey][value]); - return accumulator; - } - }; - } - } - - Promise.all( - _.reduce( - destinationCodes, - (sum, languageKey) => { - const fileName = _.template('<%= languageKey %>.json')({ - languageKey - }); - - //read languageKey Cache. - getCache(languageKey); - - //Starts with the top level strings - return sum.concat( - _.reduce( - iterLeaves(JSON.parse(fs.readFileSync(path.resolve(inputFile), 'utf-8')), undefined, undefined, languageKey), - (promiseChain, fn) => { - return promiseChain.then(fn); - }, - Promise.resolve() - ) - .then((payload) => { - fs.writeFileSync('./../../apps/red-ui/src/assets/i18n/' + fileName, JSON.stringify(payload)); - }) - .then(_.partial(console.log, 'Successfully translated all nodes, file output at ' + fileName)) - ); - }, - [] - ) - ).then(() => { - process.exit(); - }); -} else { - console.error('You must provide an input json file and a comma-separated list of destination language codes.'); -} diff --git a/tools/auto-i18n/unflatten.js b/tools/auto-i18n/unflatten.js new file mode 100644 index 000000000..257b00163 --- /dev/null +++ b/tools/auto-i18n/unflatten.js @@ -0,0 +1,78 @@ +const fs = require('fs'); +const axios = require('axios'); + +function flatten(data) { + const result = {}; + + function recurse(cur, prop) { + if (Object(cur) !== cur) { + result[prop] = cur; + } else if (Array.isArray(cur)) { + for (let i = 0, l = cur.length; i < l; i++) recurse(cur[i], prop + '[' + i + ']'); + if (l === 0) result[prop] = []; + } else { + let isEmpty = true; + for (const p in cur) { + isEmpty = false; + recurse(cur[p], prop ? prop + '.' + p : p); + } + if (isEmpty && prop) result[prop] = {}; + } + } + + recurse(data, ''); + return result; +} + +function unflatten(data) { + if (Object(data) !== data || Array.isArray(data)) return data; + const regex = /\.?([^.\[\]]+)|\[(\d+)\]/g, + resultholder = {}; + for (const p in data) { + let cur = resultholder, + prop = '', + m; + while ((m = regex.exec(p))) { + cur = cur[prop] || (cur[prop] = m[2] ? [] : {}); + prop = m[2] || m[1]; + } + cur[prop] = data[p]; + } + return resultholder[''] || resultholder; +} + +async function execute() { + // const flatGerman = JSON.parse(fs.readFileSync('de-flat.json', 'utf-8')); + + const german = JSON.parse(fs.readFileSync('./../../apps/red-ui/src/assets/i18n/de.json', 'utf-8')); + const flatGerman = flatten(german); + + const english = JSON.parse(fs.readFileSync('./../../apps/red-ui/src/assets/i18n/en.json', 'utf-8')); + + const flatEnglish = flatten(english); + + const apiKey = 'AIzaSyBiqNTundSKFjAJnSb4wSVLDU6w0Kv651M'; + + for (const key of Object.keys(flatEnglish)) { + if (!flatGerman[key]) { + const value = flatEnglish[key]; + const apiUrl = `https://www.googleapis.com/language/translate/v2?key=${apiKey}&q=${value}&source=en&target=de`; + + const response = await axios.get(apiUrl); + let translated = flatEnglish[key]; + try { + translated = response.data.data.translations[0].translatedText; + } catch (e) {} + console.log('missing: ' + key + ' -> ' + flatEnglish[key] + ' -> ' + translated); + flatGerman[key] = translated; + } + } + + const mergedGerman = { ...flatEnglish, ...flatGerman }; + + const finalGerman = unflatten(mergedGerman); + + fs.writeFileSync('./../../apps/red-ui/src/assets/i18n/de.json', JSON.stringify(finalGerman)); +} + +execute().then(); diff --git a/yarn.lock b/yarn.lock index 1e748cb1c..b42ca5d49 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3982,6 +3982,13 @@ axios@^0.18.0: follow-redirects "1.5.10" is-buffer "^2.0.2" +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -7323,6 +7330,11 @@ follow-redirects@^1.0.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== +follow-redirects@^1.14.4: + version "1.14.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381" + integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"