From 9e2a682a516d4804ed545a32c0bfba12d0e6e094 Mon Sep 17 00:00:00 2001 From: nikunj59 Date: Fri, 24 Jun 2022 19:26:30 +0530 Subject: [PATCH 01/97] CST-6153 changes for current password field introduce --- ...ofile-page-security-form.component.spec.ts | 13 +++++++++++ .../profile-page-security-form.component.ts | 21 +++++++++++++----- .../profile-page/profile-page.component.html | 1 + .../profile-page.component.spec.ts | 9 ++++++-- .../profile-page/profile-page.component.ts | 22 ++++++++++++++----- src/assets/i18n/en.json5 | 2 ++ 6 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts index 213a83b86e..ba758b1203 100644 --- a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts +++ b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts @@ -74,6 +74,19 @@ describe('ProfilePageSecurityFormComponent', () => { expect(component.passwordValue.emit).toHaveBeenCalledWith('new-password'); })); + + it('should emit the value on password change with current password for profile-page', fakeAsync(() => { + spyOn(component.passwordValue, 'emit'); + spyOn(component.currentPasswordValue, 'emit'); + component.FORM_PREFIX = 'profile.security.form.'; + component.ngOnInit(); + component.formGroup.patchValue({password: 'new-password'}); + component.formGroup.patchValue({'current-password': 'current-password'}); + tick(300); + + expect(component.passwordValue.emit).toHaveBeenCalledWith('new-password'); + expect(component.currentPasswordValue.emit).toHaveBeenCalledWith('current-password'); + })) }); }); }); diff --git a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts index 4f310204e3..ab39ca1929 100644 --- a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts +++ b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts @@ -27,6 +27,10 @@ export class ProfilePageSecurityFormComponent implements OnInit { * Emits the value of the password */ @Output() passwordValue = new EventEmitter(); + /** + * Emits the value of the current-password + */ + @Output() currentPasswordValue = new EventEmitter(); /** * The form's input models @@ -69,6 +73,14 @@ export class ProfilePageSecurityFormComponent implements OnInit { } ngOnInit(): void { + if (this.FORM_PREFIX === 'profile.security.form.') { + this.formModel.unshift(new DynamicInputModel({ + id: 'current-password', + name: 'current-password', + inputType: 'password', + required: true + })); + } if (this.passwordCanBeEmpty) { this.formGroup = this.formService.createFormGroup(this.formModel, {validators: [this.checkPasswordsEqual, this.checkPasswordLength]}); @@ -85,11 +97,7 @@ export class ProfilePageSecurityFormComponent implements OnInit { this.subs.push(this.formGroup.statusChanges.pipe( debounceTime(300), map((status: string) => { - if (status !== 'VALID') { - return true; - } else { - return false; - } + return status !== 'VALID'; })).subscribe((status) => this.isInvalid.emit(status)) ); @@ -97,6 +105,9 @@ export class ProfilePageSecurityFormComponent implements OnInit { debounceTime(300), ).subscribe((valueChange) => { this.passwordValue.emit(valueChange.password); + if (this.FORM_PREFIX === 'profile.security.form.') { + this.currentPasswordValue.emit(valueChange['current-password']); + } })); } diff --git a/src/app/profile-page/profile-page.component.html b/src/app/profile-page/profile-page.component.html index 6e22f73a75..b6f53b08bf 100644 --- a/src/app/profile-page/profile-page.component.html +++ b/src/app/profile-page/profile-page.component.html @@ -24,6 +24,7 @@ [FORM_PREFIX]="'profile.security.form.'" (isInvalid)="setInvalid($event)" (passwordValue)="setPasswordValue($event)" + (currentPasswordValue)="setCurrentPasswordValue($event)" > diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 6893ac2437..71537e9c32 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -180,7 +180,7 @@ describe('ProfilePageComponent', () => { beforeEach(() => { component.setPasswordValue(''); - + component.setCurrentPasswordValue('current-password'); result = component.updateSecurity(); }); @@ -199,6 +199,7 @@ describe('ProfilePageComponent', () => { beforeEach(() => { component.setPasswordValue('test'); component.setInvalid(true); + component.setCurrentPasswordValue('current-password'); result = component.updateSecurity(); }); @@ -215,8 +216,12 @@ describe('ProfilePageComponent', () => { beforeEach(() => { component.setPasswordValue('testest'); component.setInvalid(false); + component.setCurrentPasswordValue('current-password'); - operations = [{ op: 'add', path: '/password', value: 'testest' }]; + operations = [ + { op: 'add', path: '/password', value: 'testest' }, + { op: 'add', path: '/challenge', value: 'current-password' } + ]; result = component.updateSecurity(); }); diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index 5629a1ae18..15811ee77f 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -67,6 +67,10 @@ export class ProfilePageComponent implements OnInit { * The password filled in, in the security form */ private password: string; + /** + * The current-password filled in, in the security form + */ + private currentPassword: string; /** * The authenticated user @@ -138,15 +142,15 @@ export class ProfilePageComponent implements OnInit { */ updateSecurity() { const passEntered = isNotEmpty(this.password); - if (this.invalidSecurity) { this.notificationsService.error(this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'error.general')); } if (!this.invalidSecurity && passEntered) { - const operation = {op: 'add', path: '/password', value: this.password} as Operation; - this.epersonService.patch(this.currentUser, [operation]).pipe( - getFirstCompletedRemoteData() - ).subscribe((response: RemoteData) => { + const operations = [ + { op: 'add', path: '/password', value: this.password }, + { op: 'add', path: '/challenge', value: this.currentPassword } + ] as Operation[]; + this.epersonService.patch(this.currentUser, operations).pipe(getFirstCompletedRemoteData()).subscribe((response: RemoteData) => { if (response.hasSucceeded) { this.notificationsService.success( this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'success.title'), @@ -170,6 +174,14 @@ export class ProfilePageComponent implements OnInit { this.password = $event; } + /** + * Set the current-password value based on the value emitted from the security form + * @param $event + */ + setCurrentPasswordValue($event: string) { + this.currentPassword = $event; + } + /** * Submit of the security form that triggers the updateProfile method */ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 3d5f15b4f2..860db5aac6 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3046,6 +3046,8 @@ "profile.security.form.label.passwordrepeat": "Retype to confirm", + "profile.security.form.label.current-password": "Current password", + "profile.security.form.notifications.success.content": "Your changes to the password were saved.", "profile.security.form.notifications.success.title": "Password saved", From 36560e0e6500d646c2ec1608f7b6a23800c22ce6 Mon Sep 17 00:00:00 2001 From: nikunj59 Date: Mon, 27 Jun 2022 20:24:46 +0530 Subject: [PATCH 02/97] CST-6153 added test case --- .../profile-page.component.spec.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 71537e9c32..31332a5fd7 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -233,6 +233,29 @@ describe('ProfilePageComponent', () => { expect(epersonService.patch).toHaveBeenCalledWith(user, operations); }); }); + + describe('when password is filled in, and is valid but return 403', () => { + let result; + let operations; + + it('should return call epersonService.patch', (done) => { + epersonService.patch.and.returnValue(observableOf(Object.assign(new RestResponse(false, 403, 'Error')))); + component.setPasswordValue('testest'); + component.setInvalid(false); + component.setCurrentPasswordValue('current-password'); + operations = [ + { op: 'add', path: '/password', value: 'testest' }, + { op: 'add', path: '/challenge', value: 'current-password' } + ]; + result = component.updateSecurity(); + epersonService.patch(user, operations).subscribe((response) => { + expect(response.statusCode).toEqual(403); + done(); + }); + expect(epersonService.patch).toHaveBeenCalledWith(user, operations); + expect(result).toEqual(true); + }); + }); }); describe('canChangePassword$', () => { From 10bbb01a442d03725b5825b9372a834ba809bd25 Mon Sep 17 00:00:00 2001 From: nikunj59 Date: Thu, 30 Jun 2022 14:24:51 +0530 Subject: [PATCH 03/97] CST-6153 added error msg for required field of security form --- .../profile-page-security-form.component.spec.ts | 2 +- src/assets/i18n/en.json5 | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts index ba758b1203..88f50e3dea 100644 --- a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts +++ b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts @@ -86,7 +86,7 @@ describe('ProfilePageSecurityFormComponent', () => { expect(component.passwordValue.emit).toHaveBeenCalledWith('new-password'); expect(component.currentPasswordValue.emit).toHaveBeenCalledWith('current-password'); - })) + })); }); }); }); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 1abcd551a6..4a6fb33e25 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3060,6 +3060,8 @@ "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", + "profile.security.form.notifications.error.general": "Please fill required fields of security form.", + "profile.title": "Update Profile", "profile.card.researcher": "Researcher Profile", From 2d7b5768bf438cc4598599453dedfd8cca779e5e Mon Sep 17 00:00:00 2001 From: Nikunj Sharma Date: Tue, 9 Aug 2022 13:25:03 +0530 Subject: [PATCH 04/97] CST-6153 changes for challange sign update --- src/app/profile-page/profile-page.component.spec.ts | 6 ++---- src/app/profile-page/profile-page.component.ts | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 31332a5fd7..66351144d5 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -219,8 +219,7 @@ describe('ProfilePageComponent', () => { component.setCurrentPasswordValue('current-password'); operations = [ - { op: 'add', path: '/password', value: 'testest' }, - { op: 'add', path: '/challenge', value: 'current-password' } + { "op": "add", "path": "/password", "value": { "password": "testest", "challenge": "current-password" } } ]; result = component.updateSecurity(); }); @@ -244,8 +243,7 @@ describe('ProfilePageComponent', () => { component.setInvalid(false); component.setCurrentPasswordValue('current-password'); operations = [ - { op: 'add', path: '/password', value: 'testest' }, - { op: 'add', path: '/challenge', value: 'current-password' } + { "op": "add", "path": "/password", "value": {"password": "testest", "challenge": "current-password" }} ]; result = component.updateSecurity(); epersonService.patch(user, operations).subscribe((response) => { diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index 15811ee77f..c171502d33 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -147,8 +147,7 @@ export class ProfilePageComponent implements OnInit { } if (!this.invalidSecurity && passEntered) { const operations = [ - { op: 'add', path: '/password', value: this.password }, - { op: 'add', path: '/challenge', value: this.currentPassword } + { "op": "add", "path": "/password", "value": { "password": this.password, "challenge": this.currentPassword } } ] as Operation[]; this.epersonService.patch(this.currentUser, operations).pipe(getFirstCompletedRemoteData()).subscribe((response: RemoteData) => { if (response.hasSucceeded) { From fa20e9e5c0d5ef5da5b5ce5f439817539939f3b5 Mon Sep 17 00:00:00 2001 From: Pierre Lasou Date: Fri, 26 Aug 2022 13:34:27 -0400 Subject: [PATCH 05/97] Adding missing language parameters --- src/assets/i18n/fr.json5 | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/assets/i18n/fr.json5 b/src/assets/i18n/fr.json5 index 5cfb7ff099..ff778eb9f8 100644 --- a/src/assets/i18n/fr.json5 +++ b/src/assets/i18n/fr.json5 @@ -1215,6 +1215,17 @@ // "collection.edit.tabs.authorizations.title": "Collection Edit - Authorizations", "collection.edit.tabs.authorizations.title": "Édition de collection - Autorisations", + //"collection.edit.item.authorizations.load-bundle-button": "Load more bundles", + "collection.edit.item.authorizations.load-bundle-button": "Charger plus de bundles", + + //"collection.edit.item.authorizations.load-more-button": "Load more", + "collection.edit.item.authorizations.load-more-button": "Charger plus", + + //"collection.edit.item.authorizations.show-bitstreams-button": "Show bitstream policies for bundle", + "collection.edit.item.authorizations.show-bitstreams-button": "Afficher les politiques de bitstream policies pour le bundle", + + + // "collection.edit.tabs.metadata.head": "Edit Metadata", "collection.edit.tabs.metadata.head": "Éditer les Métadonnées", @@ -2909,6 +2920,13 @@ // "item.search.title": "Item Search", "item.search.title": "Recherche d'Items", + + // "item.truncatable-part.show-more": "Show more", + "item.truncatable-part.show-more": "Voir plus", + + //"item.truncatable-part.show-less": "Collapse", + "item.truncatable-part.show-less": "Réduire", + // "item.page.abstract": "Abstract", "item.page.abstract": "Résumé", @@ -3572,6 +3590,9 @@ // "menu.section.processes": "Processes", "menu.section.processes": "Processus", + + // "menu.section.health": "Health", + "menu.section.health": "Santé du système", // "menu.section.registries": "Registries", "menu.section.registries": "Registres", @@ -4808,6 +4829,9 @@ // "default.search.results.head": "Search Results", "default.search.results.head": "Résultats de recherche", + + // "default-relationships.search.results.head": "Search Results", + "default-relationships.search.results.head": "Résultats de recherche", // "search.sidebar.close": "Back to results", "search.sidebar.close": "Retour aux résultats", From 72e5909b713cb39022cccbdca298ff252faeffba Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 1 Sep 2022 19:02:19 +0200 Subject: [PATCH 06/97] 94060: MyDSpace Workflow/Workspace item display as correct entity types --- .../my-dspace-page/my-dspace-search.module.ts | 2 + ...-search-result-list-element.component.html | 13 +++---- ...arch-result-list-element.component.spec.ts | 9 +++-- ...em-search-result-list-element.component.ts | 36 +++++++++-------- ...-search-result-list-element.component.html | 17 ++++---- ...arch-result-list-element.component.spec.ts | 9 +++-- ...em-search-result-list-element.component.ts | 39 +++++++++++-------- 7 files changed, 68 insertions(+), 57 deletions(-) diff --git a/src/app/my-dspace-page/my-dspace-search.module.ts b/src/app/my-dspace-page/my-dspace-search.module.ts index a97f2207e7..d2c975b352 100644 --- a/src/app/my-dspace-page/my-dspace-search.module.ts +++ b/src/app/my-dspace-page/my-dspace-search.module.ts @@ -16,6 +16,7 @@ import { WorkflowItemSearchResultListElementComponent } from '../shared/object-l import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component'; import { ClaimedApprovedSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component'; import { ClaimedDeclinedSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component'; +import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -38,6 +39,7 @@ const ENTRY_COMPONENTS = [ CommonModule, SharedModule, MyDspacePageRoutingModule, + ResearchEntitiesModule.withEntryComponents() ], declarations: [ ...ENTRY_COMPONENTS diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.html index 74fc5fd06d..2529bbb012 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.html +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.html @@ -1,11 +1,10 @@ - - - + + + diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts index 61337b0cb3..609e53dfdb 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts @@ -83,14 +83,15 @@ describe('WorkflowItemSearchResultListElementComponent', () => { })); beforeEach(() => { - component.dso = mockResultObject.indexableObject; + component.object = mockResultObject; fixture.detectChanges(); }); - it('should init item properly', (done) => { - component.item$.pipe(take(1)).subscribe((i) => { + it('should init derivedSearchResult$ properly', (done) => { + component.derivedSearchResult$.pipe(take(1)).subscribe((i) => { expect(linkService.resolveLink).toHaveBeenCalled(); - expect(i).toBe(item); + expect(i.indexableObject).toBe(item); + expect(i.hitHighlights).toBe(mockResultObject.hitHighlights); done(); }); }); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts index 836a3ee268..455be79ec6 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts @@ -1,14 +1,12 @@ import { Component } from '@angular/core'; import { Observable } from 'rxjs'; -import { find, map } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { LinkService } from '../../../../core/cache/builders/link.service'; -import { RemoteData } from '../../../../core/data/remote-data'; import { Item } from '../../../../core/shared/item.model'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; -import { isNotUndefined } from '../../../empty.util'; import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; @@ -16,6 +14,9 @@ import { TruncatableService } from '../../../truncatable/truncatable.service'; import { followLink } from '../../../utils/follow-link-config.model'; import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; +import { CollectionElementLinkType } from '../../../object-collection/collection-element-link.type'; /** * This component renders workflowitem object for the search result in the list view. @@ -28,11 +29,14 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; @listableObjectComponent(WorkflowItemSearchResult, ViewMode.ListElement) export class WorkflowItemSearchResultListElementComponent extends SearchResultListElementComponent { + LinkTypes = CollectionElementLinkType; + + ViewModes = ViewMode; /** - * The item object that belonging to the result object + * The item search result derived from the WorkspaceItemSearchResult */ - public item$: Observable; + derivedSearchResult$: Observable; /** * Represent item's status @@ -52,18 +56,18 @@ export class WorkflowItemSearchResultListElementComponent extends SearchResultLi */ ngOnInit() { super.ngOnInit(); - this.linkService.resolveLink(this.dso, followLink('item')); - this.initItem(this.dso.item as Observable> ); + this.deriveSearchResult(); } - /** - * Retrieve item from result object - */ - initItem(item$: Observable>) { - this.item$ = item$.pipe( - find((rd: RemoteData) => rd.hasSucceeded && isNotUndefined(rd.payload)), - map((rd: RemoteData) => rd.payload) - ); + private deriveSearchResult() { + this.linkService.resolveLink(this.object.indexableObject, followLink('item')); + this.derivedSearchResult$ = this.object.indexableObject.item.pipe( + getFirstSucceededRemoteDataPayload(), + map((item: Item) => { + const result = new ItemSearchResult(); + result.indexableObject = item; + result.hitHighlights = this.object.hitHighlights; + return result; + })); } - } diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.html index 41d95b87af..76cf207f00 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.html +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.html @@ -1,11 +1,10 @@ - - - - + + + + + *ngIf="!(derivedSearchResult$ | async)" + [showMessage]="false"> diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts index 87f5fd3733..eaabd7503d 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts @@ -82,14 +82,15 @@ describe('WorkspaceItemSearchResultListElementComponent', () => { })); beforeEach(() => { - component.dso = mockResultObject.indexableObject; + component.object = mockResultObject; fixture.detectChanges(); }); - it('should init item properly', (done) => { - component.item$.pipe(take(1)).subscribe((i) => { + it('should init derivedSearchResult$ properly', (done) => { + component.derivedSearchResult$.pipe(take(1)).subscribe((i) => { expect(linkService.resolveLink).toHaveBeenCalled(); - expect(i).toBe(item); + expect(i.indexableObject).toBe(item); + expect(i.hitHighlights).toBe(mockResultObject.hitHighlights); done(); }); }); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts index 5edfc1929e..e76886beb1 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts @@ -1,21 +1,22 @@ import { Component } from '@angular/core'; import { Observable } from 'rxjs'; -import { find, map } from 'rxjs/operators'; import { LinkService } from '../../../../core/cache/builders/link.service'; -import { RemoteData } from '../../../../core/data/remote-data'; import { Item } from '../../../../core/shared/item.model'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; -import { isNotUndefined } from '../../../empty.util'; import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkspaceItemSearchResult } from '../../../object-collection/shared/workspace-item-search-result.model'; import { TruncatableService } from '../../../truncatable/truncatable.service'; -import { followLink } from '../../../utils/follow-link-config.model'; import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; +import { map } from 'rxjs/operators'; +import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; +import { CollectionElementLinkType } from '../../../object-collection/collection-element-link.type'; +import { followLink } from '../../../utils/follow-link-config.model'; /** * This component renders workspaceitem object for the search result in the list view. @@ -27,12 +28,15 @@ import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service'; }) @listableObjectComponent(WorkspaceItemSearchResult, ViewMode.ListElement) -export class WorkspaceItemSearchResultListElementComponent extends SearchResultListElementComponent { +export class WorkspaceItemSearchResultListElementComponent extends SearchResultListElementComponent { + LinkTypes = CollectionElementLinkType; + + ViewModes = ViewMode; /** - * The item object that belonging to the result object + * The item search result derived from the WorkspaceItemSearchResult */ - item$: Observable; + derivedSearchResult$: Observable; /** * Represent item's status @@ -52,17 +56,18 @@ export class WorkspaceItemSearchResultListElementComponent extends SearchResultL */ ngOnInit() { super.ngOnInit(); - this.linkService.resolveLink(this.dso, followLink('item')); - this.initItem(this.dso.item as Observable>); + this.deriveSearchResult(); } - /** - * Retrieve item from result object - */ - initItem(item$: Observable>) { - this.item$ = item$.pipe( - find((rd: RemoteData) => rd.hasSucceeded && isNotUndefined(rd.payload)), - map((rd: RemoteData) => rd.payload) - ); + private deriveSearchResult() { + this.linkService.resolveLink(this.object.indexableObject, followLink('item')); + this.derivedSearchResult$ = this.object.indexableObject.item.pipe( + getFirstSucceededRemoteDataPayload(), + map((item: Item) => { + const result = new ItemSearchResult(); + result.indexableObject = item; + result.hitHighlights = this.object.hitHighlights; + return result; + })); } } From 3c5fe8e098600fbd96631e061ad3108edc123079 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 6 Sep 2022 10:11:23 +0200 Subject: [PATCH 07/97] 94060: added fallback titles for person and orgunit list elements --- ...org-unit-search-result-list-element.component.html | 4 ++-- .../person-search-result-list-element.component.html | 4 ++-- .../person-search-result-list-element.component.ts | 11 ++++++++--- src/assets/i18n/en.json5 | 2 ++ 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html index fb0ad21b6e..5ffea9b920 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html @@ -2,10 +2,10 @@ + [innerHTML]="firstMetadataValue('organization.legalName') || ('orgunit.listelement.no-title' | translate)"> + [innerHTML]="firstMetadataValue('organization.legalName') || ('orgunit.listelement.no-title' | translate)"> + [innerHTML]="name || ('person.listelement.no-title' | translate)"> + [innerHTML]="name || ('person.listelement.no-title' | translate)"> Date: Tue, 6 Sep 2022 17:02:25 +0530 Subject: [PATCH 08/97] CST-6153 updated lint error --- src/app/profile-page/profile-page.component.spec.ts | 4 ++-- src/app/profile-page/profile-page.component.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 66351144d5..c1bfe8e6bb 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -219,7 +219,7 @@ describe('ProfilePageComponent', () => { component.setCurrentPasswordValue('current-password'); operations = [ - { "op": "add", "path": "/password", "value": { "password": "testest", "challenge": "current-password" } } + { 'op': 'add', 'path': '/password', 'value': { 'password': 'testest', 'challenge': 'current-password' } } ]; result = component.updateSecurity(); }); @@ -243,7 +243,7 @@ describe('ProfilePageComponent', () => { component.setInvalid(false); component.setCurrentPasswordValue('current-password'); operations = [ - { "op": "add", "path": "/password", "value": {"password": "testest", "challenge": "current-password" }} + { 'op': 'add', 'path': '/password', 'value': {'password': 'testest', 'challenge': 'current-password' }} ]; result = component.updateSecurity(); epersonService.patch(user, operations).subscribe((response) => { diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index c171502d33..5432a0303c 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -147,7 +147,7 @@ export class ProfilePageComponent implements OnInit { } if (!this.invalidSecurity && passEntered) { const operations = [ - { "op": "add", "path": "/password", "value": { "password": this.password, "challenge": this.currentPassword } } + { 'op': 'add', 'path': '/password', 'value': { 'password': this.password, 'challenge': this.currentPassword } } ] as Operation[]; this.epersonService.patch(this.currentUser, operations).pipe(getFirstCompletedRemoteData()).subscribe((response: RemoteData) => { if (response.hasSucceeded) { From f15440ca5a3ef2ec93f5a2397c7c9521ea6c6f61 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 6 Sep 2022 15:33:56 +0200 Subject: [PATCH 09/97] 94060: Fixed test issues --- ...org-unit-search-result-list-element.component.spec.ts | 9 +++++++++ .../person-search-result-list-element.component.spec.ts | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts index d116b2ade7..2876c7921d 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts @@ -9,6 +9,8 @@ import { TruncatableService } from '../../../../../shared/truncatable/truncatabl import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from '../../../../../shared/mocks/translate-loader.mock'; let orgUnitListElementComponent: OrgUnitSearchResultListElementComponent; let fixture: ComponentFixture; @@ -53,6 +55,13 @@ const mockItemWithoutMetadata: ItemSearchResult = Object.assign( describe('OrgUnitSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + } + )], declarations: [ OrgUnitSearchResultListElementComponent , TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts index 2acb02da7d..4de3f52f4c 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts @@ -9,6 +9,8 @@ import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service'; import { DSONameServiceMock } from '../../../../../shared/mocks/dso-name.service.mock'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateLoaderMock } from '../../../../../shared/mocks/translate-loader.mock'; let personListElementComponent: PersonSearchResultListElementComponent; let fixture: ComponentFixture; @@ -53,6 +55,13 @@ const mockItemWithoutMetadata: ItemSearchResult = Object.assign( describe('PersonSearchResultListElementComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateLoaderMock + } + } + )], declarations: [PersonSearchResultListElementComponent, TruncatePipe], providers: [ { provide: TruncatableService, useValue: {} }, From d88352f51378cb8705e24cfa3fcdb4db6a9278a8 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Wed, 7 Sep 2022 13:49:11 +0200 Subject: [PATCH 10/97] 94031: Fix findById for concat fields As far as I can tell the suffix is never used with a numeric part, causing this branch to always miss concat group fields --- src/app/shared/form/builder/form-builder.service.spec.ts | 9 +++++++++ src/app/shared/form/builder/form-builder.service.ts | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/app/shared/form/builder/form-builder.service.spec.ts b/src/app/shared/form/builder/form-builder.service.spec.ts index ac9c2b652b..b68963e5ad 100644 --- a/src/app/shared/form/builder/form-builder.service.spec.ts +++ b/src/app/shared/form/builder/form-builder.service.spec.ts @@ -325,6 +325,14 @@ describe('FormBuilderService test suite', () => { typeBindRelations: [{ match: 'VISIBLE', operator: 'OR', when: [{id: 'dc.type', value: 'Book' }]}] }, ), + + new DynamicConcatModel({ + id: 'testConcatGroup_CONCAT_GROUP', + group: [ + new DynamicInputModel({ id: 'testConcatGroup_CONCAT_FIRST_INPUT' }), + new DynamicInputModel({ id: 'testConcatGroup_CONCAT_SECOND_INPUT' }), + ] + } as any) ]; testFormConfiguration = { @@ -463,6 +471,7 @@ describe('FormBuilderService test suite', () => { expect(service.findById('testTimePicker', testModel) instanceof DynamicTimePickerModel).toBe(true); expect(service.findById('testRating', testModel) instanceof DynamicRatingModel).toBe(true); expect(service.findById('testColorPicker', testModel) instanceof DynamicColorPickerModel).toBe(true); + expect(service.findById('testConcatGroup', testModel) instanceof DynamicConcatModel).toBe(true); }); it('should find a nested dynamic form control model by id', () => { diff --git a/src/app/shared/form/builder/form-builder.service.ts b/src/app/shared/form/builder/form-builder.service.ts index 93a398a59d..a281942bc7 100644 --- a/src/app/shared/form/builder/form-builder.service.ts +++ b/src/app/shared/form/builder/form-builder.service.ts @@ -116,8 +116,8 @@ export class FormBuilderService extends DynamicFormService { } if (this.isConcatGroup(controlModel)) { - if (controlModel.id.match(new RegExp(findId + CONCAT_GROUP_SUFFIX + `_\\d+$`))) { - result = (controlModel as DynamicConcatModel).group[0]; + if (controlModel.id.match(new RegExp(findId + CONCAT_GROUP_SUFFIX))) { + result = (controlModel as DynamicConcatModel); break; } } From 5a0ad41bfd132c236c31166eb4c1da0d3c7fbb3e Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Wed, 7 Sep 2022 13:49:28 +0200 Subject: [PATCH 11/97] 94301: Trickle down errors to concat field inputs When a concat group is marked as invalid ~ server error, its fields should also be marked as invalid --- src/app/shared/form/form.service.spec.ts | 59 +++++++++++++++++++++++- src/app/shared/form/form.service.ts | 20 +++++++- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/app/shared/form/form.service.spec.ts b/src/app/shared/form/form.service.spec.ts index 6370a5f4ba..25afe803b5 100644 --- a/src/app/shared/form/form.service.spec.ts +++ b/src/app/shared/form/form.service.spec.ts @@ -108,8 +108,15 @@ describe('FormService test suite', () => { const title: AbstractControl = new FormControl(undefined, Validators.required); const date: AbstractControl = new FormControl(undefined); const description: AbstractControl = new FormControl(undefined); - formGroup = new FormGroup({ author, title, date, description }); - controls = { author, title, date, description }; + + const addressLocation: FormGroup = new FormGroup({ + zipCode: new FormControl(undefined), + state: new FormControl(undefined), + city: new FormControl(undefined), + }); + + formGroup = new FormGroup({ author, title, date, description, addressLocation }); + controls = { author, title, date, description , addressLocation }; service = new FormService(builderService, store); }) ) @@ -179,6 +186,30 @@ describe('FormService test suite', () => { expect(formGroup.controls.description.touched).toBe(true); }); + it('should add errors to fields of group', () => { + let control = controls.addressLocation; + let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'addressLocation'); + let errorKeys: string[]; + + service.addErrorToField(control, model, 'Test error message'); + + // the group itself should get an error + errorKeys = Object.keys(control.errors); + expect(errorKeys.length).toBe(1); + expect(control.hasError(errorKeys[0])).toBe(true); + + expect(control.touched).toBe(true); + + // the group's inputs should get an error + Object.values(control.controls).forEach((subControl: AbstractControl) => { + errorKeys = Object.keys(subControl.errors); + expect(errorKeys.length).toBe(1); + expect(subControl.hasError(errorKeys[0])).toBe(true); + expect(subControl.touched).toBe(true); + }); + + }); + it('should remove error from field', () => { let control = controls.description; let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'description'); @@ -209,6 +240,30 @@ describe('FormService test suite', () => { expect(formGroup.controls.description.touched).toBe(false); }); + it('should remove errors from fields of group', () => { + let control = controls.addressLocation; + let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'addressLocation'); + let errorKeys: string[]; + + service.addErrorToField(control, model, 'Test error message'); + errorKeys = Object.keys(control.errors); + + service.removeErrorFromField(control, model, errorKeys[0]); + + // the group itself should no longer have an error + expect(errorKeys.length).toBe(1); + expect(control.hasError(errorKeys[0])).toBe(false); + expect(control.touched).toBe(false); + + // the group's inputs should no longer have an error + Object.values(control.controls).forEach((subControl: AbstractControl) => { + errorKeys = Object.keys(subControl.errors); + expect(errorKeys.length).toBe(1); + expect(subControl.hasError(errorKeys[0])).toBe(false); + expect(subControl.touched).toBe(false); + }); + }); + it('should reset form group', () => { const control = controls.author; diff --git a/src/app/shared/form/form.service.ts b/src/app/shared/form/form.service.ts index 8a7eb184a8..b2f6de4240 100644 --- a/src/app/shared/form/form.service.ts +++ b/src/app/shared/form/form.service.ts @@ -7,7 +7,7 @@ import { select, Store } from '@ngrx/store'; import { AppState } from '../../app.reducer'; import { formObjectFromIdSelector } from './selectors'; import { FormBuilderService } from './builder/form-builder.service'; -import { DynamicFormControlEvent, DynamicFormControlModel } from '@ng-dynamic-forms/core'; +import { DynamicFormControlEvent, DynamicFormControlModel, DynamicFormGroupModel } from '@ng-dynamic-forms/core'; import { isEmpty, isNotUndefined } from '../empty.util'; import { uniqueId } from 'lodash'; import { @@ -161,6 +161,15 @@ export class FormService { field.setErrors(error); } + // if the field in question is a group, pass down the error to its fields + if (field instanceof FormGroup && model instanceof DynamicFormGroupModel) { + model.group.forEach((subModel) => { + const subField = field.controls[subModel.id]; + + this.addErrorToField(subField, subModel, message); + }); + } + field.markAsTouched(); } @@ -173,6 +182,15 @@ export class FormService { field.setErrors(error); } + // if the field in question is a group, clear the error from its fields + if (field instanceof FormGroup && model instanceof DynamicFormGroupModel) { + model.group.forEach((subModel) => { + const subField = field.controls[subModel.id]; + + this.removeErrorFromField(subField, subModel, messageKey); + }); + } + field.markAsUntouched(); } From 744bcae3f2dfc245c6daf52fe079488bb6ec8388 Mon Sep 17 00:00:00 2001 From: Yura Bondarenko Date: Wed, 7 Sep 2022 13:50:44 +0200 Subject: [PATCH 12/97] 94031: Hide error messages of concat field inputs Hint/error is shown at the group level, shouldn't be repeated in the inner inputs --- ...namic-form-control-container.component.html | 2 +- .../models/ds-dynamic-input.model.ts | 4 +++- .../builder/parsers/concat-field-parser.ts | 18 +++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index 7eef1d8655..dfad396b40 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -22,7 +22,7 @@
-
{{ message | translate: model.validators }}
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts index ed99acb34e..613b965612 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts @@ -27,7 +27,7 @@ export interface DsDynamicInputModelConfig extends DynamicInputModelConfig { hasSelectableMetadata: boolean; metadataValue?: FormFieldMetadataValueObject; isModelOfInnerForm?: boolean; - + hideRequiredHint?: boolean; } export class DsDynamicInputModel extends DynamicInputModel { @@ -46,6 +46,7 @@ export class DsDynamicInputModel extends DynamicInputModel { @serializable() hasSelectableMetadata: boolean; @serializable() metadataValue: FormFieldMetadataValueObject; @serializable() isModelOfInnerForm: boolean; + @serializable() hideRequiredHint?: boolean; constructor(config: DsDynamicInputModelConfig, layout?: DynamicFormControlLayout) { @@ -61,6 +62,7 @@ export class DsDynamicInputModel extends DynamicInputModel { this.metadataValue = config.metadataValue; this.place = config.place; this.isModelOfInnerForm = (hasValue(config.isModelOfInnerForm) ? config.isModelOfInnerForm : false); + this.hideRequiredHint = config.hideRequiredHint; this.language = config.language; if (!this.language) { diff --git a/src/app/shared/form/builder/parsers/concat-field-parser.ts b/src/app/shared/form/builder/parsers/concat-field-parser.ts index 2de5f256dc..f7c8c0e627 100644 --- a/src/app/shared/form/builder/parsers/concat-field-parser.ts +++ b/src/app/shared/form/builder/parsers/concat-field-parser.ts @@ -1,11 +1,7 @@ import {Inject} from '@angular/core'; import { FormFieldModel } from '../models/form-field.model'; import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model'; -import { - DynamicFormControlLayout, - DynamicInputModel, - DynamicInputModelConfig -} from '@ng-dynamic-forms/core'; +import { DynamicFormControlLayout, } from '@ng-dynamic-forms/core'; import { CONCAT_FIRST_INPUT_SUFFIX, CONCAT_GROUP_SUFFIX, @@ -22,6 +18,7 @@ import { PARSER_OPTIONS, SUBMISSION_ID } from './field-parser'; +import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-form-ui/models/ds-dynamic-input.model'; export class ConcatFieldParser extends FieldParser { @@ -58,14 +55,14 @@ export class ConcatFieldParser extends FieldParser { concatGroup.group = []; concatGroup.separator = this.separator; - const input1ModelConfig: DynamicInputModelConfig = this.initModel( + const input1ModelConfig: DsDynamicInputModelConfig = this.initModel( id + CONCAT_FIRST_INPUT_SUFFIX, false, true, true, false ); - const input2ModelConfig: DynamicInputModelConfig = this.initModel( + const input2ModelConfig: DsDynamicInputModelConfig = this.initModel( id + CONCAT_SECOND_INPUT_SUFFIX, false, true, @@ -73,6 +70,9 @@ export class ConcatFieldParser extends FieldParser { false ); + input1ModelConfig.hideRequiredHint = true; + input2ModelConfig.hideRequiredHint = true; + if (hasNoValue(concatGroup.hint) && hasValue(input1ModelConfig.hint) && hasNoValue(input2ModelConfig.hint)) { concatGroup.hint = input1ModelConfig.hint; input1ModelConfig.hint = undefined; @@ -98,8 +98,8 @@ export class ConcatFieldParser extends FieldParser { input2ModelConfig.placeholder = placeholder[1]; } - const model1 = new DynamicInputModel(input1ModelConfig, clsInput); - const model2 = new DynamicInputModel(input2ModelConfig, clsInput); + const model1 = new DsDynamicInputModel(input1ModelConfig, clsInput); + const model2 = new DsDynamicInputModel(input2ModelConfig, clsInput); concatGroup.group.push(model1); concatGroup.group.push(model2); From d40f163c4916c4fdad7c859980ef195f6976bc97 Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Thu, 8 Sep 2022 13:25:41 +0200 Subject: [PATCH 13/97] 94273: Implement dependencies between requests When an object is invalidated, its dependent requests are invalidated as well --- src/app/core/cache/object-cache.actions.ts | 48 ++++++- .../core/cache/object-cache.reducer.spec.ts | 28 +++- src/app/core/cache/object-cache.reducer.ts | 66 ++++++++- .../core/cache/object-cache.service.spec.ts | 133 +++++++++++++++++- src/app/core/cache/object-cache.service.ts | 107 ++++++++++++-- src/app/core/data/data.service.spec.ts | 58 +++++++- src/app/core/data/data.service.ts | 45 +++++- .../core/eperson/group-data.service.spec.ts | 29 ++-- .../shared/mocks/object-cache.service.mock.ts | 2 + 9 files changed, 468 insertions(+), 48 deletions(-) diff --git a/src/app/core/cache/object-cache.actions.ts b/src/app/core/cache/object-cache.actions.ts index 88b4730b3f..8c83f6104e 100644 --- a/src/app/core/cache/object-cache.actions.ts +++ b/src/app/core/cache/object-cache.actions.ts @@ -13,7 +13,9 @@ export const ObjectCacheActionTypes = { REMOVE: type('dspace/core/cache/object/REMOVE'), RESET_TIMESTAMPS: type('dspace/core/cache/object/RESET_TIMESTAMPS'), ADD_PATCH: type('dspace/core/cache/object/ADD_PATCH'), - APPLY_PATCH: type('dspace/core/cache/object/APPLY_PATCH') + APPLY_PATCH: type('dspace/core/cache/object/APPLY_PATCH'), + ADD_DEPENDENTS: type('dspace/core/cache/object/ADD_DEPENDENTS'), + REMOVE_DEPENDENTS: type('dspace/core/cache/object/REMOVE_DEPENDENTS') }; /** @@ -126,13 +128,49 @@ export class ApplyPatchObjectCacheAction implements Action { } } +export class AddDependentsObjectCacheAction implements Action { + type = ObjectCacheActionTypes.ADD_DEPENDENTS; + payload: { + href: string; + dependentRequestUUIDs: string[]; + }; + + /** + * Create a new AddDependencyObjectCacheAction + * + * @param href the self link of a cached object + * @param dependentRequestUUIDs the UUID of the request that depends on this object + */ + constructor(href: string, dependentRequestUUIDs: string[]) { + this.payload = { + href, + dependentRequestUUIDs, + }; + } +} + +export class RemoveDependentsObjectCacheAction implements Action { + type = ObjectCacheActionTypes.REMOVE_DEPENDENTS; + payload: string; + + /** + * Create a new AddDependencyObjectCacheAction + * + * @param href the self link of a cached object for which to remove all dependent request UUIDs + */ + constructor(href: string) { + this.payload = href; + } +} /** * A type to encompass all ObjectCacheActions */ export type ObjectCacheAction = AddToObjectCacheAction - | RemoveFromObjectCacheAction - | ResetObjectCacheTimestampsAction - | AddPatchObjectCacheAction - | ApplyPatchObjectCacheAction; + | RemoveFromObjectCacheAction + | ResetObjectCacheTimestampsAction + | AddPatchObjectCacheAction + | ApplyPatchObjectCacheAction + | AddDependentsObjectCacheAction + | RemoveDependentsObjectCacheAction; diff --git a/src/app/core/cache/object-cache.reducer.spec.ts b/src/app/core/cache/object-cache.reducer.spec.ts index 82e2da58b1..e346a00b61 100644 --- a/src/app/core/cache/object-cache.reducer.spec.ts +++ b/src/app/core/cache/object-cache.reducer.spec.ts @@ -2,11 +2,13 @@ import * as deepFreeze from 'deep-freeze'; import { Operation } from 'fast-json-patch'; import { Item } from '../shared/item.model'; import { + AddDependentsObjectCacheAction, AddPatchObjectCacheAction, AddToObjectCacheAction, ApplyPatchObjectCacheAction, + RemoveDependentsObjectCacheAction, RemoveFromObjectCacheAction, - ResetObjectCacheTimestampsAction + ResetObjectCacheTimestampsAction, } from './object-cache.actions'; import { objectCacheReducer } from './object-cache.reducer'; @@ -42,20 +44,22 @@ describe('objectCacheReducer', () => { timeCompleted: new Date().getTime(), msToLive: 900000, requestUUIDs: [requestUUID1], + dependentRequestUUIDs: [], patches: [], isDirty: false, }, [selfLink2]: { data: { type: Item.type, - self: requestUUID2, + self: selfLink2, foo: 'baz', - _links: { self: { href: requestUUID2 } } + _links: { self: { href: selfLink2 } } }, alternativeLinks: [altLink3, altLink4], timeCompleted: new Date().getTime(), msToLive: 900000, - requestUUIDs: [selfLink2], + requestUUIDs: [requestUUID2], + dependentRequestUUIDs: [requestUUID1], patches: [], isDirty: false } @@ -189,4 +193,20 @@ describe('objectCacheReducer', () => { expect((newState[selfLink1].data as any).name).toEqual(newName); }); + it('should add dependent requests on ADD_DEPENDENTS', () => { + let newState = objectCacheReducer(testState, new AddDependentsObjectCacheAction(selfLink1, ['new', 'newer', 'newest'])); + expect(newState[selfLink1].dependentRequestUUIDs).toEqual(['new', 'newer', 'newest']); + + newState = objectCacheReducer(newState, new AddDependentsObjectCacheAction(selfLink2, ['more'])); + expect(newState[selfLink2].dependentRequestUUIDs).toEqual([requestUUID1, 'more']); + }); + + it('should clear dependent requests on REMOVE_DEPENDENTS', () => { + let newState = objectCacheReducer(testState, new RemoveDependentsObjectCacheAction(selfLink1)); + expect(newState[selfLink1].dependentRequestUUIDs).toEqual([]); + + newState = objectCacheReducer(newState, new RemoveDependentsObjectCacheAction(selfLink2)); + expect(newState[selfLink2].dependentRequestUUIDs).toEqual([]); + }); + }); diff --git a/src/app/core/cache/object-cache.reducer.ts b/src/app/core/cache/object-cache.reducer.ts index 1a42408f72..dc3f50db68 100644 --- a/src/app/core/cache/object-cache.reducer.ts +++ b/src/app/core/cache/object-cache.reducer.ts @@ -1,12 +1,13 @@ /* eslint-disable max-classes-per-file */ import { + AddDependentsObjectCacheAction, AddPatchObjectCacheAction, AddToObjectCacheAction, ApplyPatchObjectCacheAction, ObjectCacheAction, - ObjectCacheActionTypes, + ObjectCacheActionTypes, RemoveDependentsObjectCacheAction, RemoveFromObjectCacheAction, - ResetObjectCacheTimestampsAction + ResetObjectCacheTimestampsAction, } from './object-cache.actions'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { CacheEntry } from './cache-entry'; @@ -69,6 +70,12 @@ export class ObjectCacheEntry implements CacheEntry { */ requestUUIDs: string[]; + /** + * A list of UUIDs for the requests that depend on this object. + * When this object is invalidated, these requests will be invalidated as well. + */ + dependentRequestUUIDs: string[]; + /** * An array of patches that were made on the client side to this entry, but haven't been sent to the server yet */ @@ -134,6 +141,14 @@ export function objectCacheReducer(state = initialState, action: ObjectCacheActi return applyPatchObjectCache(state, action as ApplyPatchObjectCacheAction); } + case ObjectCacheActionTypes.ADD_DEPENDENTS: { + return addDependentsObjectCacheState(state, action as AddDependentsObjectCacheAction); + } + + case ObjectCacheActionTypes.REMOVE_DEPENDENTS: { + return removeDependentsObjectCacheState(state, action as RemoveDependentsObjectCacheAction); + } + default: { return state; } @@ -159,6 +174,7 @@ function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheActio timeCompleted: action.payload.timeCompleted, msToLive: action.payload.msToLive, requestUUIDs: [action.payload.requestUUID, ...(existing.requestUUIDs || [])], + dependentRequestUUIDs: existing.dependentRequestUUIDs || [], isDirty: isNotEmpty(existing.patches), patches: existing.patches || [], alternativeLinks: [...(existing.alternativeLinks || []), ...newAltLinks] @@ -252,3 +268,49 @@ function applyPatchObjectCache(state: ObjectCacheState, action: ApplyPatchObject } return newState; } + +/** + * Add a list of dependent request UUIDs to a cached object, used when defining new dependencies + * + * @param state the current state + * @param action an AddDependentsObjectCacheAction + * @return the new state, with the dependent requests of the cached object updated + */ +function addDependentsObjectCacheState(state: ObjectCacheState, action: AddDependentsObjectCacheAction): ObjectCacheState { + const href = action.payload.href; + const newState = Object.assign({}, state); + + if (hasValue(newState[href])) { + newState[href] = Object.assign({}, newState[href], { + dependentRequestUUIDs: [ + ...new Set([ + ...newState[href]?.dependentRequestUUIDs || [], + ...action.payload.dependentRequestUUIDs, + ]) + ] + }); + } + + return newState; +} + + +/** + * Remove all dependent request UUIDs from a cached object, used to clear out-of-date depedencies + * + * @param state the current state + * @param action an AddDependentsObjectCacheAction + * @return the new state, with the dependent requests of the cached object updated + */ +function removeDependentsObjectCacheState(state: ObjectCacheState, action: RemoveDependentsObjectCacheAction): ObjectCacheState { + const href = action.payload; + const newState = Object.assign({}, state); + + if (hasValue(newState[href])) { + newState[href] = Object.assign({}, newState[href], { + dependentRequestUUIDs: [] + }); + } + + return newState; +} diff --git a/src/app/core/cache/object-cache.service.spec.ts b/src/app/core/cache/object-cache.service.spec.ts index f18c262524..6af797be29 100644 --- a/src/app/core/cache/object-cache.service.spec.ts +++ b/src/app/core/cache/object-cache.service.spec.ts @@ -11,10 +11,12 @@ import { coreReducers} from '../core.reducers'; import { RestRequestMethod } from '../data/rest-request-method'; import { Item } from '../shared/item.model'; import { + AddDependentsObjectCacheAction, + RemoveDependentsObjectCacheAction, AddPatchObjectCacheAction, AddToObjectCacheAction, ApplyPatchObjectCacheAction, - RemoveFromObjectCacheAction + RemoveFromObjectCacheAction, } from './object-cache.actions'; import { Patch } from './object-cache.reducer'; import { ObjectCacheService } from './object-cache.service'; @@ -25,6 +27,7 @@ import { storeModuleConfig } from '../../app.reducer'; import { TestColdObservable } from 'jasmine-marbles/src/test-observables'; import { IndexName } from '../index/index-name.model'; import { CoreState } from '../core-state.model'; +import { TestScheduler } from 'rxjs/testing'; describe('ObjectCacheService', () => { let service: ObjectCacheService; @@ -38,6 +41,7 @@ describe('ObjectCacheService', () => { let altLink1; let altLink2; let requestUUID; + let requestUUID2; let alternativeLink; let timestamp; let timestamp2; @@ -55,6 +59,7 @@ describe('ObjectCacheService', () => { altLink1 = 'https://alternative.link/endpoint/1234'; altLink2 = 'https://alternative.link/endpoint/5678'; requestUUID = '4d3a4ce8-a375-4b98-859b-39f0a014d736'; + requestUUID2 = 'c0f486c1-c4d3-4a03-b293-ca5b71ff0054'; alternativeLink = 'https://rest.api/endpoint/5e4f8a5-be98-4c51-9fd8-6bfedcbd59b7/item'; timestamp = new Date().getTime(); timestamp2 = new Date().getTime() - 200; @@ -71,13 +76,17 @@ describe('ObjectCacheService', () => { data: objectToCache, timeCompleted: timestamp, msToLive: msToLive, - alternativeLinks: [altLink1, altLink2] + alternativeLinks: [altLink1, altLink2], + requestUUIDs: [requestUUID], + dependentRequestUUIDs: [], }; cacheEntry2 = { data: objectToCache, timeCompleted: timestamp2, msToLive: msToLive2, - alternativeLinks: [altLink2] + alternativeLinks: [altLink2], + requestUUIDs: [requestUUID2], + dependentRequestUUIDs: [], }; invalidCacheEntry = Object.assign({}, cacheEntry, { msToLive: -1 }); operations = [{ op: 'replace', path: '/name', value: 'random string' } as Operation]; @@ -343,4 +352,122 @@ describe('ObjectCacheService', () => { expect(store.dispatch).toHaveBeenCalledWith(new ApplyPatchObjectCacheAction(selfLink)); }); }); + + describe('request dependencies', () => { + beforeEach(() => { + const state = Object.assign({}, initialState, { + core: Object.assign({}, initialState.core, { + 'cache/object': { + ['objectWithoutDependents']: { + dependentRequestUUIDs: [], + }, + ['objectWithDependents']: { + dependentRequestUUIDs: [requestUUID], + }, + [selfLink]: cacheEntry, + }, + 'index': { + 'object/alt-link-to-self-link': { + [anotherLink]: selfLink, + ['objectWithoutDependentsAlt']: 'objectWithoutDependents', + ['objectWithDependentsAlt']: 'objectWithDependents', + } + } + }) + }); + mockStore.setState(state); + }); + + describe('addDependency', () => { + it('should dispatch an ADD_DEPENDENTS action', () => { + service.addDependency(selfLink, 'objectWithoutDependents'); + expect(store.dispatch).toHaveBeenCalledOnceWith(new AddDependentsObjectCacheAction('objectWithoutDependents', [requestUUID])); + }); + + it('should resolve alt links', () => { + service.addDependency(anotherLink, 'objectWithoutDependentsAlt'); + expect(store.dispatch).toHaveBeenCalledOnceWith(new AddDependentsObjectCacheAction('objectWithoutDependents', [requestUUID])); + }); + + it('should not dispatch if either href cannot be resolved to a cached self link', () => { + service.addDependency(selfLink, 'unknown'); + service.addDependency('unknown', 'objectWithoutDependents'); + service.addDependency('nothing', 'matches'); + expect(store.dispatch).not.toHaveBeenCalled(); + }); + + it('should not dispatch if either href is undefined', () => { + service.addDependency(selfLink, undefined); + service.addDependency(undefined, 'objectWithoutDependents'); + service.addDependency(undefined, undefined); + expect(store.dispatch).not.toHaveBeenCalled(); + }); + + it('should not dispatch if the dependency exists already', () => { + service.addDependency(selfLink, 'objectWithDependents'); + expect(store.dispatch).not.toHaveBeenCalled(); + }); + + it('should work with observable hrefs', () => { + service.addDependency(observableOf(selfLink), observableOf('objectWithoutDependents')); + expect(store.dispatch).toHaveBeenCalledOnceWith(new AddDependentsObjectCacheAction('objectWithoutDependents', [requestUUID])); + }); + + it('should only dispatch once for the first value of either observable href', () => { + const testScheduler = new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + + testScheduler.run(({ cold: tsCold, flush }) => { + const href$ = tsCold('--y-n-n', { + y: selfLink, + n: 'NOPE' + }); + const dependsOnHref$ = tsCold('-y-n-n', { + y: 'objectWithoutDependents', + n: 'NOPE' + }); + + service.addDependency(href$, dependsOnHref$); + flush(); + + expect(store.dispatch).toHaveBeenCalledOnceWith(new AddDependentsObjectCacheAction('objectWithoutDependents', [requestUUID])); + }); + }); + + it('should not dispatch if either of the hrefs emits undefined', () => { + const testScheduler = new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + + testScheduler.run(({ cold: tsCold, flush }) => { + const undefined$ = tsCold('--u'); + + service.addDependency(selfLink, undefined$); + service.addDependency(undefined$, 'objectWithoutDependents'); + service.addDependency(undefined$, undefined$); + flush(); + + expect(store.dispatch).not.toHaveBeenCalled(); + }); + }); + }); + + describe('removeDependents', () => { + it('should dispatch a REMOVE_DEPENDENTS action', () => { + service.removeDependents('objectWithDependents'); + expect(store.dispatch).toHaveBeenCalledOnceWith(new RemoveDependentsObjectCacheAction('objectWithDependents')); + }); + + it('should resolve alt links', () => { + service.removeDependents('objectWithDependentsAlt'); + expect(store.dispatch).toHaveBeenCalledOnceWith(new RemoveDependentsObjectCacheAction('objectWithDependents')); + }); + + it('should not dispatch if the href cannot be resolved to a cached self link', () => { + service.removeDependents('unknown'); + expect(store.dispatch).not.toHaveBeenCalled(); + }); + }); + }); }); diff --git a/src/app/core/cache/object-cache.service.ts b/src/app/core/cache/object-cache.service.ts index cdf87e5c1a..9ca0216210 100644 --- a/src/app/core/cache/object-cache.service.ts +++ b/src/app/core/cache/object-cache.service.ts @@ -4,23 +4,15 @@ import { applyPatch, Operation } from 'fast-json-patch'; import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; import { distinctUntilChanged, filter, map, mergeMap, switchMap, take } from 'rxjs/operators'; -import { hasValue, isNotEmpty, isEmpty } from '../../shared/empty.util'; +import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { CoreState } from '../core-state.model'; import { coreSelector } from '../core.selectors'; import { RestRequestMethod } from '../data/rest-request-method'; -import { - selfLinkFromAlternativeLinkSelector, - selfLinkFromUuidSelector -} from '../index/index.selectors'; +import { selfLinkFromAlternativeLinkSelector, selfLinkFromUuidSelector } from '../index/index.selectors'; import { GenericConstructor } from '../shared/generic-constructor'; import { getClassForType } from './builders/build-decorators'; import { LinkService } from './builders/link.service'; -import { - AddPatchObjectCacheAction, - AddToObjectCacheAction, - ApplyPatchObjectCacheAction, - RemoveFromObjectCacheAction -} from './object-cache.actions'; +import { AddDependentsObjectCacheAction, AddPatchObjectCacheAction, AddToObjectCacheAction, ApplyPatchObjectCacheAction, RemoveDependentsObjectCacheAction, RemoveFromObjectCacheAction } from './object-cache.actions'; import { ObjectCacheEntry, ObjectCacheState } from './object-cache.reducer'; import { AddToSSBAction } from './server-sync-buffer.actions'; @@ -339,4 +331,97 @@ export class ObjectCacheService { this.store.dispatch(new ApplyPatchObjectCacheAction(selfLink)); } + /** + * Add a new dependency between two cached objects. + * When {@link dependsOnHref$} is invalidated, {@link href$} will be invalidated as well. + * + * This method should be called _after_ requests have been sent; + * it will only work if both objects are already present in the cache. + * + * If either object is undefined, the dependency will not be added + * + * @param href$ the href of an object to add a dependency to + * @param dependsOnHref$ the href of the new dependency + */ + addDependency(href$: string | Observable, dependsOnHref$: string | Observable) { + if (hasNoValue(href$) || hasNoValue(dependsOnHref$)) { + return; + } + + if (typeof href$ === 'string') { + href$ = observableOf(href$); + } + if (typeof dependsOnHref$ === 'string') { + dependsOnHref$ = observableOf(dependsOnHref$); + } + + observableCombineLatest([ + href$, + dependsOnHref$.pipe( + switchMap(dependsOnHref => this.resolveSelfLink(dependsOnHref)) + ), + ]).pipe( + switchMap(([href, dependsOnSelfLink]: [string, string]) => { + const dependsOnSelfLink$ = observableOf(dependsOnSelfLink); + + return observableCombineLatest([ + dependsOnSelfLink$, + dependsOnSelfLink$.pipe( + switchMap(selfLink => this.getBySelfLink(selfLink)), + map(oce => oce?.dependentRequestUUIDs || []), + ), + this.getByHref(href).pipe( + // only add the latest request to keep dependency index from growing indefinitely + map((entry: ObjectCacheEntry) => entry?.requestUUIDs?.[0]), + ) + ]); + }), + take(1), + ).subscribe(([dependsOnSelfLink, currentDependents, newDependent]: [string, string[], string]) => { + // don't dispatch if either href is invalid or if the new dependency already exists + if (hasValue(dependsOnSelfLink) && hasValue(newDependent) && !currentDependents.includes(newDependent)) { + this.store.dispatch(new AddDependentsObjectCacheAction(dependsOnSelfLink, [newDependent])); + } + }); + } + + /** + * Clear all dependent requests associated with a cache entry. + * + * @href the href of a cached object + */ + removeDependents(href: string) { + this.resolveSelfLink(href).pipe( + take(1), + ).subscribe((selfLink: string) => { + if (hasValue(selfLink)) { + this.store.dispatch(new RemoveDependentsObjectCacheAction(selfLink)); + } + }); + } + + + /** + * Resolve the self link of an existing cached object from an arbitrary href + * + * @param href any href + * @return an observable of the self link corresponding to the given href. + * Will emit the given href if it was a self link, another href + * if the given href was an alt link, or undefined if there is no + * cached object for this href. + */ + private resolveSelfLink(href: string): Observable { + return this.getBySelfLink(href).pipe( + switchMap((oce: ObjectCacheEntry) => { + if (isNotEmpty(oce)) { + return [href]; + } else { + return this.store.pipe( + select(selfLinkFromAlternativeLinkSelector(href)), + ); + } + }), + ); + } + } diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index b8c41dee9d..cdac1f2855 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http'; import { Store } from '@ngrx/store'; import { compare, Operation } from 'fast-json-patch'; -import { Observable, of as observableOf } from 'rxjs'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { followLink } from '../../shared/utils/follow-link-config.model'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; @@ -13,6 +13,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { Item } from '../shared/item.model'; import { createFailedRemoteDataObject, + createFailedRemoteDataObject$, createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$, } from '../../shared/remote-data.utils'; @@ -96,7 +97,13 @@ describe('DataService', () => { }, getByHref: () => { /* empty */ - } + }, + addDependency: () => { + /* empty */ + }, + removeDependents: () => { + /* empty */ + }, } as any; store = {} as Store; selfLink = 'https://rest.api/endpoint/1698f1d3-be98-4c51-9fd8-6bfedcbd59b7'; @@ -849,7 +856,8 @@ describe('DataService', () => { beforeEach(() => { getByHrefSpy = spyOn(objectCache, 'getByHref').and.returnValue(observableOf({ - requestUUIDs: ['request1', 'request2', 'request3'] + requestUUIDs: ['request1', 'request2', 'request3'], + dependentRequestUUIDs: [] })); }); @@ -898,9 +906,9 @@ describe('DataService', () => { it('should only fire for the current state of the object (instead of tracking it)', () => { testScheduler.run(({ cold, flush }) => { getByHrefSpy.and.returnValue(cold('a---b---c---', { - a: { requestUUIDs: ['request1'] }, // this is the state at the moment we're invalidating the cache - b: { requestUUIDs: ['request2'] }, // we shouldn't keep tracking the state - c: { requestUUIDs: ['request3'] }, // because we may invalidate when we shouldn't + a: { requestUUIDs: ['request1'], dependentRequestUUIDs: [] }, // this is the state at the moment we're invalidating the cache + b: { requestUUIDs: ['request2'], dependentRequestUUIDs: [] }, // we shouldn't keep tracking the state + c: { requestUUIDs: ['request3'], dependentRequestUUIDs: [] }, // because we may invalidate when we shouldn't })); service.invalidateByHref('some-href'); @@ -970,4 +978,42 @@ describe('DataService', () => { }); }); }); + + describe('addDependency', () => { + let addDependencySpy; + + beforeEach(() => { + addDependencySpy = spyOn(objectCache, 'addDependency'); + }); + + it('should call objectCache.addDependency with the object\'s self link', () => { + addDependencySpy.and.callFake((href$: Observable, dependsOn$: Observable) => { + observableCombineLatest([href$, dependsOn$]).subscribe(([href, dependsOn]) => { + expect(href).toBe('object-href'); + expect(dependsOn).toBe('dependsOnHref'); + }); + }); + + (service as any).addDependency( + createSuccessfulRemoteDataObject$({ _links: { self: { href: 'object-href' } } }), + observableOf('dependsOnHref') + ); + expect(addDependencySpy).toHaveBeenCalled(); + }); + + it('should call objectCache.addDependency without an href if request failed', () => { + addDependencySpy.and.callFake((href$: Observable, dependsOn$: Observable) => { + observableCombineLatest([href$, dependsOn$]).subscribe(([href, dependsOn]) => { + expect(href).toBe(undefined); + expect(dependsOn).toBe('dependsOnHref'); + }); + }); + + (service as any).addDependency( + createFailedRemoteDataObject$('something went wrong'), + observableOf('dependsOnHref') + ); + expect(addDependencySpy).toHaveBeenCalled(); + }); + }); }); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index c17fccb198..6f260bae25 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -27,7 +27,7 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { DSpaceSerializer } from '../dspace-rest/dspace.serializer'; import { DSpaceObject } from '../shared/dspace-object.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../shared/operators'; +import { getFirstSucceededRemoteData, getRemoteDataPayload, getFirstCompletedRemoteData } from '../shared/operators'; import { URLCombiner } from '../url-combiner/url-combiner'; import { ChangeAnalyzer } from './change-analyzer'; import { PaginatedList } from './paginated-list.model'; @@ -576,6 +576,35 @@ export abstract class DataService implements UpdateDa return result$; } + /** + * Shorthand method to add a dependency to a cached object + * ``` + * const out$ = this.findByHref(...); // or another method that sends a request + * this.addDependency(out$, dependsOnHref); + * ``` + * When {@link dependsOnHref$} is invalidated, {@link object$} will be invalidated as well. + * + * + * @param object$ the cached object + * @param dependsOnHref$ the href of the object it should depend on + */ + protected addDependency(object$: Observable>>, dependsOnHref$: string | Observable) { + this.objectCache.addDependency( + object$.pipe( + getFirstCompletedRemoteData(), + switchMap((rd: RemoteData) => { + if (rd.hasSucceeded) { + return [rd.payload._links.self.href]; + } else { + // undefined href will be skipped in objectCache.addDependency + return [undefined]; + } + }), + ), + dependsOnHref$ + ); + } + /** * Invalidate an existing DSpaceObject by marking all requests it is included in as stale * @param objectId The id of the object to be invalidated @@ -597,11 +626,17 @@ export abstract class DataService implements UpdateDa this.objectCache.getByHref(href).pipe( take(1), - switchMap((oce: ObjectCacheEntry) => observableFrom(oce.requestUUIDs).pipe( - mergeMap((requestUUID: string) => this.requestService.setStaleByUUID(requestUUID)), - toArray(), - )), + switchMap((oce: ObjectCacheEntry) => { + return observableFrom([ + ...oce.requestUUIDs, + ...oce.dependentRequestUUIDs + ]).pipe( + mergeMap((requestUUID: string) => this.requestService.setStaleByUUID(requestUUID)), + toArray(), + ); + }), ).subscribe(() => { + this.objectCache.removeDependents(href); done$.next(true); done$.complete(); }); diff --git a/src/app/core/eperson/group-data.service.spec.ts b/src/app/core/eperson/group-data.service.spec.ts index c1b9e59d5b..8f5e92aaf6 100644 --- a/src/app/core/eperson/group-data.service.spec.ts +++ b/src/app/core/eperson/group-data.service.spec.ts @@ -27,11 +27,10 @@ import { createPaginatedList, createRequestEntry$ } from '../../shared/testing/u import { CoreState } from '../core-state.model'; import { FindListOptions } from '../data/find-list-options.model'; import { DataService } from '../data/data.service'; -import { ObjectCacheService } from '../cache/object-cache.service'; -import { getMockLinkService } from '../../shared/mocks/link-service.mock'; import { DataServiceStub } from '../../shared/testing/data-service.stub'; import { of as observableOf } from 'rxjs'; import { ObjectCacheEntry } from '../cache/object-cache.reducer'; +import { getMockObjectCacheService } from '../../shared/mocks/object-cache.service.mock'; describe('GroupDataService', () => { let service: GroupDataService; @@ -44,7 +43,7 @@ describe('GroupDataService', () => { let groups$; let halService; let rdbService; - let objectCache: ObjectCacheService; + let objectCache; let dataService: DataServiceStub; function init() { @@ -54,7 +53,9 @@ describe('GroupDataService', () => { groups$ = createSuccessfulRemoteDataObject$(createPaginatedList(groups)); rdbService = getMockRemoteDataBuildServiceHrefMap(undefined, { 'https://dspace.4science.it/dspace-spring-rest/api/eperson/groups': groups$ }); halService = new HALEndpointServiceStub(restEndpointURL); - objectCache = new ObjectCacheService(store, getMockLinkService()); + + objectCache = getMockObjectCacheService(); + dataService = new DataServiceStub(); TestBed.configureTestingModule({ imports: [ @@ -122,8 +123,9 @@ describe('GroupDataService', () => { describe('addSubGroupToGroup', () => { beforeEach(() => { - spyOn(objectCache, 'getByHref').and.returnValue(observableOf({ - requestUUIDs: ['request1', 'request2'] + objectCache.getByHref.and.returnValue(observableOf({ + requestUUIDs: ['request1', 'request2'], + dependentRequestUUIDs: [], } as ObjectCacheEntry)); spyOn(dataService, 'invalidateByHref'); service.addSubGroupToGroup(GroupMock, GroupMock2).subscribe(); @@ -151,8 +153,9 @@ describe('GroupDataService', () => { describe('deleteSubGroupFromGroup', () => { beforeEach(() => { - spyOn(objectCache, 'getByHref').and.returnValue(observableOf({ - requestUUIDs: ['request1', 'request2'] + objectCache.getByHref.and.returnValue(observableOf({ + requestUUIDs: ['request1', 'request2'], + dependentRequestUUIDs: [], } as ObjectCacheEntry)); spyOn(dataService, 'invalidateByHref'); service.deleteSubGroupFromGroup(GroupMock, GroupMock2).subscribe(); @@ -176,8 +179,9 @@ describe('GroupDataService', () => { describe('addMemberToGroup', () => { beforeEach(() => { - spyOn(objectCache, 'getByHref').and.returnValue(observableOf({ - requestUUIDs: ['request1', 'request2'] + objectCache.getByHref.and.returnValue(observableOf({ + requestUUIDs: ['request1', 'request2'], + dependentRequestUUIDs: [], } as ObjectCacheEntry)); spyOn(dataService, 'invalidateByHref'); service.addMemberToGroup(GroupMock, EPersonMock2).subscribe(); @@ -206,8 +210,9 @@ describe('GroupDataService', () => { describe('deleteMemberFromGroup', () => { beforeEach(() => { - spyOn(objectCache, 'getByHref').and.returnValue(observableOf({ - requestUUIDs: ['request1', 'request2'] + objectCache.getByHref.and.returnValue(observableOf({ + requestUUIDs: ['request1', 'request2'], + dependentRequestUUIDs: [], } as ObjectCacheEntry)); spyOn(dataService, 'invalidateByHref'); service.deleteMemberFromGroup(GroupMock, EPersonMock).subscribe(); diff --git a/src/app/shared/mocks/object-cache.service.mock.ts b/src/app/shared/mocks/object-cache.service.mock.ts index 515c2abe86..8cceaefc3d 100644 --- a/src/app/shared/mocks/object-cache.service.mock.ts +++ b/src/app/shared/mocks/object-cache.service.mock.ts @@ -13,6 +13,8 @@ export function getMockObjectCacheService(): ObjectCacheService { 'hasByUUID', 'hasByHref', 'getRequestUUIDBySelfLink', + 'addDependency', + 'removeDependents', ]); } From 7c13db2f89701039a3aa2d699268389a91062155 Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Thu, 8 Sep 2022 13:26:01 +0200 Subject: [PATCH 14/97] 94273: Invalidate object on successful patch --- src/app/core/data/data.service.spec.ts | 24 ++++++++++++++++++++---- src/app/core/data/data.service.ts | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts index cdac1f2855..77d5771b91 100644 --- a/src/app/core/data/data.service.spec.ts +++ b/src/app/core/data/data.service.spec.ts @@ -351,7 +351,12 @@ describe('DataService', () => { describe('patch', () => { const dso = { - uuid: 'dso-uuid' + uuid: 'dso-uuid', + _links: { + self: { + href: 'dso-href', + } + } }; const operations = [ Object.assign({ @@ -361,12 +366,23 @@ describe('DataService', () => { }) as Operation ]; - beforeEach(() => { + it('should send a PatchRequest', () => { service.patch(dso, operations); + expect(requestService.send).toHaveBeenCalledWith(jasmine.any(PatchRequest)); }); - it('should send a PatchRequest', () => { - expect(requestService.send).toHaveBeenCalledWith(jasmine.any(PatchRequest)); + it('should invalidate the cached object if successfully patched', () => { + spyOn(rdbService, 'buildFromRequestUUIDAndAwait'); + spyOn(service, 'invalidateByHref'); + + service.patch(dso, operations); + + expect(rdbService.buildFromRequestUUIDAndAwait).toHaveBeenCalled(); + expect((rdbService.buildFromRequestUUIDAndAwait as jasmine.Spy).calls.argsFor(0)[0]).toBe(requestService.generateRequestId()); + const callback = (rdbService.buildFromRequestUUIDAndAwait as jasmine.Spy).calls.argsFor(0)[1]; + callback(); + + expect(service.invalidateByHref).toHaveBeenCalledWith('dso-href'); }); }); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 6f260bae25..b69d219c2e 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -484,7 +484,7 @@ export abstract class DataService implements UpdateDa this.requestService.send(request); }); - return this.rdbService.buildFromRequestUUID(requestId); + return this.rdbService.buildFromRequestUUIDAndAwait(requestId, () => this.invalidateByHref(object._links.self.href)); } createPatchFromCache(object: T): Observable { From 293ba8408e63d04e595695f01056156eef3f749a Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Thu, 8 Sep 2022 13:27:34 +0200 Subject: [PATCH 15/97] 94273: Make isAuthorized depend on the target object This ensures that a successful ItemDataService.setWithdrawn call invalidates all related authorizations --- .../authorization-data.service.spec.ts | 46 ++++++++++++++++++- .../authorization-data.service.ts | 24 ++++++++-- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/app/core/data/feature-authorization/authorization-data.service.spec.ts b/src/app/core/data/feature-authorization/authorization-data.service.spec.ts index df46d3f0a1..255ce8f741 100644 --- a/src/app/core/data/feature-authorization/authorization-data.service.spec.ts +++ b/src/app/core/data/feature-authorization/authorization-data.service.spec.ts @@ -3,7 +3,7 @@ import { SiteDataService } from '../site-data.service'; import { AuthService } from '../../auth/auth.service'; import { Site } from '../../shared/site.model'; import { EPerson } from '../../eperson/models/eperson.model'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { FeatureID } from './feature-id'; import { hasValue } from '../../../shared/empty.util'; import { RequestParam } from '../../cache/models/request-param.model'; @@ -17,6 +17,7 @@ describe('AuthorizationDataService', () => { let service: AuthorizationDataService; let siteService: SiteDataService; let authService: AuthService; + let objectCache; let site: Site; let ePerson: EPerson; @@ -43,7 +44,11 @@ describe('AuthorizationDataService', () => { isAuthenticated: () => observableOf(true), getAuthenticatedUserFromStore: () => observableOf(ePerson) } as AuthService; - service = new AuthorizationDataService(requestService, undefined, undefined, undefined, undefined, undefined, undefined, undefined, authService, siteService); + objectCache = jasmine.createSpyObj('objectCache', { + addDependency: undefined, + removeDependents: undefined, + }); + service = new AuthorizationDataService(requestService, undefined, undefined, objectCache, undefined, undefined, undefined, undefined, authService, siteService); } beforeEach(() => { @@ -110,6 +115,43 @@ describe('AuthorizationDataService', () => { expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(objectUrl, ePersonUuid, FeatureID.LoginOnBehalfOf), true, true); }); }); + + describe('dependencies', () => { + let addDependencySpy; + + beforeEach(() => { + (service.searchBy as any).and.returnValue(observableOf('searchBy RD$')); + addDependencySpy = spyOn(service as any, 'addDependency'); + }); + + it('should add a dependency on the objectUrl', (done) => { + addDependencySpy.and.callFake((href$: Observable, dependsOn$: Observable) => { + observableCombineLatest([href$, dependsOn$]).subscribe(([href, dependsOn]) => { + expect(href).toBe('searchBy RD$'); + expect(dependsOn).toBe('object-href'); + }); + }); + + service.searchByObject(FeatureID.AdministratorOf, 'object-href').subscribe(() => { + expect(addDependencySpy).toHaveBeenCalled(); + done(); + }); + }); + + it('should add a dependency on the Site object if no objectUrl is given', (done) => { + addDependencySpy.and.callFake((object$: Observable, dependsOn$: Observable) => { + observableCombineLatest([object$, dependsOn$]).subscribe(([object, dependsOn]) => { + expect(object).toBe('searchBy RD$'); + expect(dependsOn).toBe('test-site-href'); + }); + }); + + service.searchByObject(FeatureID.AdministratorOf).subscribe(() => { + expect(addDependencySpy).toHaveBeenCalled(); + done(); + }); + }); + }); }); describe('isAuthorized', () => { diff --git a/src/app/core/data/feature-authorization/authorization-data.service.ts b/src/app/core/data/feature-authorization/authorization-data.service.ts index f27919844d..008e69b119 100644 --- a/src/app/core/data/feature-authorization/authorization-data.service.ts +++ b/src/app/core/data/feature-authorization/authorization-data.service.ts @@ -18,10 +18,10 @@ import { followLink, FollowLinkConfig } from '../../../shared/utils/follow-link- import { RemoteData } from '../remote-data'; import { PaginatedList } from '../paginated-list.model'; import { catchError, map, switchMap } from 'rxjs/operators'; -import { hasValue, isNotEmpty } from '../../../shared/empty.util'; +import { hasNoValue, hasValue, isNotEmpty } from '../../../shared/empty.util'; import { RequestParam } from '../../cache/models/request-param.model'; import { AuthorizationSearchParams } from './authorization-search-params'; -import { addSiteObjectUrlIfEmpty, oneAuthorizationMatchesFeature } from './authorization-utils'; +import { oneAuthorizationMatchesFeature } from './authorization-utils'; import { FeatureID } from './feature-id'; import { getFirstCompletedRemoteData } from '../../shared/operators'; import { CoreState } from '../../core-state.model'; @@ -102,12 +102,28 @@ export class AuthorizationDataService extends DataService { * {@link HALLink}s should be automatically resolved */ searchByObject(featureId?: FeatureID, objectUrl?: string, ePersonUuid?: string, options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { - return observableOf(new AuthorizationSearchParams(objectUrl, ePersonUuid, featureId)).pipe( - addSiteObjectUrlIfEmpty(this.siteService), + const objectUrl$ = observableOf(objectUrl).pipe( + switchMap((url) => { + if (hasNoValue(url)) { + return this.siteService.find().pipe( + map((site) => site.self) + ); + } else { + return observableOf(url); + } + }), + ); + + const out$ = objectUrl$.pipe( + map((url: string) => new AuthorizationSearchParams(url, ePersonUuid, featureId)), switchMap((params: AuthorizationSearchParams) => { return this.searchBy(this.searchByObjectPath, this.createSearchOptions(params.objectUrl, options, params.ePersonUuid, params.featureId), useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); }) ); + + this.addDependency(out$, objectUrl$); + + return out$; } /** From c1498424f3605eb61cb90cc7d853ebf86305ee8f Mon Sep 17 00:00:00 2001 From: Nikunj Sharma Date: Tue, 13 Sep 2022 16:18:32 +0530 Subject: [PATCH 16/97] CST-6685 changes for import batch --- .../batch-import-page.component.html | 35 ++++ .../batch-import-page.component.spec.ts | 149 ++++++++++++++++++ .../batch-import-page.component.ts | 123 +++++++++++++++ src/app/admin/admin-routing.module.ts | 7 + src/app/admin/admin.module.ts | 4 +- .../data/processes/script-data.service.ts | 1 + src/app/menu.resolver.spec.ts | 3 + src/app/menu.resolver.ts | 27 ++-- .../dso-selector-modal-wrapper.component.ts | 1 + .../import-batch-selector.component.spec.ts | 100 ++++++++++++ .../import-batch-selector.component.ts | 45 ++++++ src/app/shared/shared.module.ts | 5 + src/assets/i18n/en.json5 | 27 +++- 13 files changed, 508 insertions(+), 19 deletions(-) create mode 100644 src/app/admin/admin-import-batch-page/batch-import-page.component.html create mode 100644 src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts create mode 100644 src/app/admin/admin-import-batch-page/batch-import-page.component.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.spec.ts create mode 100644 src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts diff --git a/src/app/admin/admin-import-batch-page/batch-import-page.component.html b/src/app/admin/admin-import-batch-page/batch-import-page.component.html new file mode 100644 index 0000000000..dbc8c74437 --- /dev/null +++ b/src/app/admin/admin-import-batch-page/batch-import-page.component.html @@ -0,0 +1,35 @@ +
+ +

{{'admin.batch-import.page.help' | translate}}

+

+ selected collection: {{getDspaceObjectName()}}  + {{'admin.batch-import.page.remove' | translate}} +

+

+ +

+
+
+ + +
+ + {{'admin.batch-import.page.validateOnly.hint' | translate}} + +
+ + + + +
+ + +
+
diff --git a/src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts b/src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts new file mode 100644 index 0000000000..eecf05f543 --- /dev/null +++ b/src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts @@ -0,0 +1,149 @@ +import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing'; +import { BatchImportPageComponent } from './batch-import-page.component'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; +import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { FormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { FileValueAccessorDirective } from '../../shared/utils/file-value-accessor.directive'; +import { FileValidator } from '../../shared/utils/require-file.validator'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { + BATCH_IMPORT_SCRIPT_NAME, + ScriptDataService +} from '../../core/data/processes/script-data.service'; +import { Router } from '@angular/router'; +import { Location } from '@angular/common'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { ProcessParameter } from '../../process-page/processes/process-parameter.model'; + +describe('BatchImportPageComponent', () => { + let component: BatchImportPageComponent; + let fixture: ComponentFixture; + + let notificationService: NotificationsServiceStub; + let scriptService: any; + let router; + let locationStub; + + function init() { + notificationService = new NotificationsServiceStub(); + scriptService = jasmine.createSpyObj('scriptService', + { + invoke: createSuccessfulRemoteDataObject$({ processId: '46' }) + } + ); + router = jasmine.createSpyObj('router', { + navigateByUrl: jasmine.createSpy('navigateByUrl') + }); + locationStub = jasmine.createSpyObj('location', { + back: jasmine.createSpy('back') + }); + } + + beforeEach(waitForAsync(() => { + init(); + TestBed.configureTestingModule({ + imports: [ + FormsModule, + TranslateModule.forRoot(), + RouterTestingModule.withRoutes([]) + ], + declarations: [BatchImportPageComponent, FileValueAccessorDirective, FileValidator], + providers: [ + { provide: NotificationsService, useValue: notificationService }, + { provide: ScriptDataService, useValue: scriptService }, + { provide: Router, useValue: router }, + { provide: Location, useValue: locationStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BatchImportPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('if back button is pressed', () => { + beforeEach(fakeAsync(() => { + const proceed = fixture.debugElement.query(By.css('#backButton')).nativeElement; + proceed.click(); + fixture.detectChanges(); + })); + it('should do location.back', () => { + expect(locationStub.back).toHaveBeenCalled(); + }); + }); + + describe('if file is set', () => { + let fileMock: File; + + beforeEach(() => { + fileMock = new File([''], 'filename.zip', { type: 'application/zip' }); + component.setFile(fileMock); + }); + + describe('if proceed button is pressed without validate only', () => { + beforeEach(fakeAsync(() => { + component.validateOnly = false; + const proceed = fixture.debugElement.query(By.css('#proceedButton')).nativeElement; + proceed.click(); + fixture.detectChanges(); + })); + it('metadata-import script is invoked with --zip fileName and the mockFile', () => { + const parameterValues: ProcessParameter[] = [ + Object.assign(new ProcessParameter(), { name: '--zip', value: 'filename.zip' }), + ]; + expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]); + }); + it('success notification is shown', () => { + expect(notificationService.success).toHaveBeenCalled(); + }); + it('redirected to process page', () => { + expect(router.navigateByUrl).toHaveBeenCalledWith('/processes/46'); + }); + }); + + describe('if proceed button is pressed with validate only', () => { + beforeEach(fakeAsync(() => { + component.validateOnly = true; + const proceed = fixture.debugElement.query(By.css('#proceedButton')).nativeElement; + proceed.click(); + fixture.detectChanges(); + })); + it('metadata-import script is invoked with --zip fileName and the mockFile and -v validate-only', () => { + const parameterValues: ProcessParameter[] = [ + Object.assign(new ProcessParameter(), { name: '--zip', value: 'filename.zip' }), + Object.assign(new ProcessParameter(), { name: '-v', value: true }), + ]; + expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]); + }); + it('success notification is shown', () => { + expect(notificationService.success).toHaveBeenCalled(); + }); + it('redirected to process page', () => { + expect(router.navigateByUrl).toHaveBeenCalledWith('/processes/46'); + }); + }); + + describe('if proceed is pressed; but script invoke fails', () => { + beforeEach(fakeAsync(() => { + jasmine.getEnv().allowRespy(true); + spyOn(scriptService, 'invoke').and.returnValue(createFailedRemoteDataObject$('Error', 500)); + const proceed = fixture.debugElement.query(By.css('#proceedButton')).nativeElement; + proceed.click(); + fixture.detectChanges(); + })); + it('error notification is shown', () => { + expect(notificationService.error).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/src/app/admin/admin-import-batch-page/batch-import-page.component.ts b/src/app/admin/admin-import-batch-page/batch-import-page.component.ts new file mode 100644 index 0000000000..2985aff3aa --- /dev/null +++ b/src/app/admin/admin-import-batch-page/batch-import-page.component.ts @@ -0,0 +1,123 @@ +import { Component } from '@angular/core'; +import { Location } from '@angular/common'; +import { TranslateService } from '@ngx-translate/core'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { BATCH_IMPORT_SCRIPT_NAME, ScriptDataService } from '../../core/data/processes/script-data.service'; +import { Router } from '@angular/router'; +import { ProcessParameter } from '../../process-page/processes/process-parameter.model'; +import { getFirstCompletedRemoteData } from '../../core/shared/operators'; +import { RemoteData } from '../../core/data/remote-data'; +import { Process } from '../../process-page/processes/process.model'; +import { isNotEmpty } from '../../shared/empty.util'; +import { getProcessDetailRoute } from '../../process-page/process-page-routing.paths'; +import { + ImportBatchSelectorComponent +} from '../../shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { take } from 'rxjs/operators'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; + +@Component({ + selector: 'ds-batch-import-page', + templateUrl: './batch-import-page.component.html' +}) +export class BatchImportPageComponent { + /** + * The current value of the file + */ + fileObject: File; + + /** + * The validate only flag + */ + validateOnly = true; + /** + * dso object for community or collection + */ + dso: DSpaceObject = null; + + public constructor(private location: Location, + protected translate: TranslateService, + protected notificationsService: NotificationsService, + private scriptDataService: ScriptDataService, + private router: Router, + private modalService: NgbModal, + private dsoNameService: DSONameService) { + } + + /** + * Set file + * @param file + */ + setFile(file) { + this.fileObject = file; + } + + /** + * When return button is pressed go to previous location + */ + public onReturn() { + this.location.back(); + } + + public selectCollection() { + const modalRef = this.modalService.open(ImportBatchSelectorComponent); + modalRef.componentInstance.response.pipe(take(1)).subscribe((dso) => { + this.dso = dso || null; + }); + } + + /** + * Starts import-metadata script with --zip fileName (and the selected file) + */ + public importMetadata() { + if (this.fileObject == null) { + this.notificationsService.error(this.translate.get('admin.metadata-import.page.error.addFile')); + } else { + const parameterValues: ProcessParameter[] = [ + Object.assign(new ProcessParameter(), { name: '--zip', value: this.fileObject.name }), + ]; + if (this.dso) { + parameterValues.push(Object.assign(new ProcessParameter(), { name: '--collection', value: this.dso.uuid })); + } + if (this.validateOnly) { + parameterValues.push(Object.assign(new ProcessParameter(), { name: '-v', value: true })); + } + + this.scriptDataService.invoke(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [this.fileObject]).pipe( + getFirstCompletedRemoteData(), + ).subscribe((rd: RemoteData) => { + if (rd.hasSucceeded) { + const title = this.translate.get('process.new.notification.success.title'); + const content = this.translate.get('process.new.notification.success.content'); + this.notificationsService.success(title, content); + if (isNotEmpty(rd.payload)) { + this.router.navigateByUrl(getProcessDetailRoute(rd.payload.processId)); + } + } else { + const title = this.translate.get('process.new.notification.error.title'); + const content = this.translate.get('process.new.notification.error.content'); + this.notificationsService.error(title, content); + } + }); + } + } + + /** + * return selected dspace object name + */ + getDspaceObjectName(): string { + if (this.dso) { + return this.dsoNameService.getName(this.dso); + } + return null; + } + + /** + * remove selected dso object + */ + removeDspaceObject(): void { + this.dso = null; + } +} diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index ee5cb8737b..1ea20bc9a0 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -7,6 +7,7 @@ import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component'; import { REGISTRIES_MODULE_PATH } from './admin-routing-paths'; +import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; @NgModule({ imports: [ @@ -40,6 +41,12 @@ import { REGISTRIES_MODULE_PATH } from './admin-routing-paths'; component: MetadataImportPageComponent, data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' } }, + { + path: 'batch-import', + resolve: { breadcrumb: I18nBreadcrumbResolver }, + component: BatchImportPageComponent, + data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' } + }, ]) ], providers: [ diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts index b28a0cf89e..0ddbefd253 100644 --- a/src/app/admin/admin.module.ts +++ b/src/app/admin/admin.module.ts @@ -9,6 +9,7 @@ import { AdminWorkflowModuleModule } from './admin-workflow-page/admin-workflow. import { AdminSearchModule } from './admin-search-page/admin-search.module'; import { AdminSidebarSectionComponent } from './admin-sidebar/admin-sidebar-section/admin-sidebar-section.component'; import { ExpandableAdminSidebarSectionComponent } from './admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component'; +import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -28,7 +29,8 @@ const ENTRY_COMPONENTS = [ ], declarations: [ AdminCurationTasksComponent, - MetadataImportPageComponent + MetadataImportPageComponent, + BatchImportPageComponent ] }) export class AdminModule { diff --git a/src/app/core/data/processes/script-data.service.ts b/src/app/core/data/processes/script-data.service.ts index 75a66c822a..91f8d591af 100644 --- a/src/app/core/data/processes/script-data.service.ts +++ b/src/app/core/data/processes/script-data.service.ts @@ -25,6 +25,7 @@ import { CoreState } from '../../core-state.model'; export const METADATA_IMPORT_SCRIPT_NAME = 'metadata-import'; export const METADATA_EXPORT_SCRIPT_NAME = 'metadata-export'; +export const BATCH_IMPORT_SCRIPT_NAME = 'batch-import'; @Injectable() @dataService(SCRIPT) diff --git a/src/app/menu.resolver.spec.ts b/src/app/menu.resolver.spec.ts index db90b7ea00..f39075ad27 100644 --- a/src/app/menu.resolver.spec.ts +++ b/src/app/menu.resolver.spec.ts @@ -259,6 +259,9 @@ describe('MenuResolver', () => { expect(menuService.addSection).toHaveBeenCalledWith(MenuID.ADMIN, jasmine.objectContaining({ id: 'import', visible: true, })); + expect(menuService.addSection).toHaveBeenCalledWith(MenuID.ADMIN, jasmine.objectContaining({ + id: 'import_batch', parentID: 'import', visible: true, + })); expect(menuService.addSection).toHaveBeenCalledWith(MenuID.ADMIN, jasmine.objectContaining({ id: 'export', visible: true, })); diff --git a/src/app/menu.resolver.ts b/src/app/menu.resolver.ts index f12079f737..a7c1fe415e 100644 --- a/src/app/menu.resolver.ts +++ b/src/app/menu.resolver.ts @@ -448,20 +448,7 @@ export class MenuResolver implements Resolve { * the import scripts exist and the current user is allowed to execute them */ createImportMenuSections() { - const menuList = [ - // TODO: enable this menu item once the feature has been implemented - // { - // id: 'import_batch', - // parentID: 'import', - // active: false, - // visible: true, - // model: { - // type: MenuItemType.LINK, - // text: 'menu.section.import_batch', - // link: '' - // } as LinkMenuItemModel, - // } - ]; + const menuList = []; menuList.forEach((menuSection) => this.menuService.addSection(MenuID.ADMIN, menuSection)); observableCombineLatest([ @@ -498,6 +485,18 @@ export class MenuResolver implements Resolve { } as LinkMenuItemModel, shouldPersistOnRouteChange: true }); + this.menuService.addSection(MenuID.ADMIN, { + id: 'import_batch', + parentID: 'import', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.import_batch', + link: '/admin/batch-import' + } as LinkMenuItemModel, + shouldPersistOnRouteChange: true + }); }); } diff --git a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts index ca8343cfad..937608a2c6 100644 --- a/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.ts @@ -10,6 +10,7 @@ export enum SelectorActionType { CREATE = 'create', EDIT = 'edit', EXPORT_METADATA = 'export-metadata', + IMPORT_BATCH = 'import-batch', SET_SCOPE = 'set-scope' } diff --git a/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.spec.ts b/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.spec.ts new file mode 100644 index 0000000000..576c1ea140 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.spec.ts @@ -0,0 +1,100 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Collection } from '../../../../core/shared/collection.model'; +import { Community } from '../../../../core/shared/community.model'; +import { Item } from '../../../../core/shared/item.model'; +import { ImportBatchSelectorComponent } from './import-batch-selector.component'; + +describe('ImportBatchSelectorComponent', () => { + let component: ImportBatchSelectorComponent; + let fixture: ComponentFixture; + const mockItem = Object.assign(new Item(), { + id: 'fake-id', + uuid: 'fake-id', + handle: 'fake/handle', + lastModified: '2018' + }); + const mockCollection: Collection = Object.assign(new Collection(), { + id: 'test-collection-1-1', + uuid: 'test-collection-1-1', + name: 'test-collection-1', + metadata: { + 'dc.identifier.uri': [ + { + language: null, + value: 'fake/test-collection-1' + } + ] + } + }); + const mockCommunity = Object.assign(new Community(), { + id: 'test-uuid', + uuid: 'test-uuid', + metadata: { + 'dc.identifier.uri': [ + { + language: null, + value: 'fake/test-community-1' + } + ] + } + }); + const modalStub = jasmine.createSpyObj('modalStub', ['close']); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], + declarations: [ImportBatchSelectorComponent], + providers: [ + { provide: NgbActiveModal, useValue: modalStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ImportBatchSelectorComponent); + component = fixture.componentInstance; + spyOn(component.response, 'emit'); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('if item is selected', () => { + beforeEach((done) => { + component.navigate(mockItem).subscribe(() => { + done(); + }); + }); + it('should emit null value', () => { + expect(component.response.emit).toHaveBeenCalledWith(null); + }); + }); + + describe('if collection is selected', () => { + beforeEach((done) => { + component.navigate(mockCollection).subscribe(() => { + done(); + }); + }); + it('should emit collection value', () => { + expect(component.response.emit).toHaveBeenCalledWith(mockCollection); + }); + }); + + describe('if community is selected', () => { + beforeEach((done) => { + component.navigate(mockCommunity).subscribe(() => { + done(); + }); + }); + it('should emit community value', () => { + expect(component.response.emit).toHaveBeenCalledWith(mockCommunity); + }); + }); +}); diff --git a/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts new file mode 100644 index 0000000000..2fdae23388 --- /dev/null +++ b/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts @@ -0,0 +1,45 @@ +import { Component, EventEmitter, OnInit, Output } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Collection } from '../../../../core/shared/collection.model'; +import { Community } from '../../../../core/shared/community.model'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../dso-selector-modal-wrapper.component'; +import { Observable, of } from 'rxjs'; + +/** + * Component to wrap a list of existing dso's inside a modal + * Used to choose a dso from to import metadata of + */ +@Component({ + selector: 'ds-import-batch-selector', + templateUrl: '../dso-selector-modal-wrapper.component.html', +}) +export class ImportBatchSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { + objectType = DSpaceObjectType.DSPACEOBJECT; + selectorTypes = [DSpaceObjectType.COLLECTION, DSpaceObjectType.COMMUNITY]; + action = SelectorActionType.IMPORT_BATCH; + /** + * An event fired when the modal is closed + */ + @Output() + response = new EventEmitter(); + + constructor(protected activeModal: NgbActiveModal, + protected route: ActivatedRoute) { + super(activeModal, route); + } + + /** + * If the dso is a collection or community: + */ + navigate(dso: DSpaceObject): Observable { + if (dso instanceof Collection || dso instanceof Community) { + this.response.emit(dso); + return of(null); + } + this.response.emit(null); + return of(null); + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 9036ff98c5..5e78796e24 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -24,6 +24,9 @@ import { ConfirmationModalComponent } from './confirmation-modal/confirmation-mo import { ExportMetadataSelectorComponent } from './dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component'; +import { + ImportBatchSelectorComponent +} from './dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component'; import { FileDropzoneNoUploaderComponent } from './file-dropzone-no-uploader/file-dropzone-no-uploader.component'; import { ItemListElementComponent } from './object-list/item-list-element/item-types/item/item-list-element.component'; import { EnumKeysPipe } from './utils/enum-keys-pipe'; @@ -468,6 +471,7 @@ const COMPONENTS = [ CollectionDropdownComponent, EntityDropdownComponent, ExportMetadataSelectorComponent, + ImportBatchSelectorComponent, ConfirmationModalComponent, VocabularyTreeviewComponent, AuthorizedCollectionSelectorComponent, @@ -545,6 +549,7 @@ const ENTRY_COMPONENTS = [ BitstreamRequestACopyPageComponent, CurationFormComponent, ExportMetadataSelectorComponent, + ImportBatchSelectorComponent, ConfirmationModalComponent, VocabularyTreeviewComponent, SidebarSearchListElementComponent, diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index bd40bc642c..171dbaa332 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -542,28 +542,45 @@ "admin.metadata-import.breadcrumbs": "Import Metadata", + "admin.batch-import.breadcrumbs": "Import Batch", + "admin.metadata-import.title": "Import Metadata", + "admin.batch-import.title": "Import Batch", + "admin.metadata-import.page.header": "Import Metadata", + "admin.batch-import.page.header": "Import Batch", + "admin.metadata-import.page.help": "You can drop or browse CSV files that contain batch metadata operations on files here", + "admin.batch-import.page.help": "You can drop or browse ZIP files that contain batch operations on files here", + "admin.metadata-import.page.dropMsg": "Drop a metadata CSV to import", + "admin.batch-import.page.dropMsg": "Drop a batch ZIP to import", + "admin.metadata-import.page.dropMsgReplace": "Drop to replace the metadata CSV to import", + "admin.batch-import.page.dropMsgReplace": "Drop to replace the batch ZIP to import", + "admin.metadata-import.page.button.return": "Back", "admin.metadata-import.page.button.proceed": "Proceed", + "admin.metadata-import.page.button.select-collection": "Select Collection", + "admin.metadata-import.page.error.addFile": "Select file first!", + "admin.batch-import.page.error.addFile": "Select Zip file first!", + "admin.metadata-import.page.validateOnly": "Validate Only", "admin.metadata-import.page.validateOnly.hint": "When selected, the uploaded CSV will be validated. You will receive a report of detected changes, but no changes will be saved.", + "admin.batch-import.page.validateOnly.hint": "When selected, the uploaded ZIP will be validated. You will receive a report of detected changes, but no changes will be saved.", - + "admin.batch-import.page.remove": "remove", "auth.errors.invalid-user": "Invalid email address or password.", @@ -640,7 +657,7 @@ "bitstream-request-a-copy.alert.canDownload2": "here", "bitstream-request-a-copy.header": "Request a copy of the file", - + "bitstream-request-a-copy.intro": "Enter the following information to request a copy for the following item: ", "bitstream-request-a-copy.intro.bitstream.one": "Requesting the following file: ", @@ -1345,6 +1362,8 @@ "dso-selector.export-metadata.dspaceobject.head": "Export metadata from", + "dso-selector.import-batch.dspaceobject.head": "Import batch from", + "dso-selector.no-results": "No {{ type }} found", "dso-selector.placeholder": "Search for a {{ type }}", @@ -2984,7 +3003,7 @@ "process.detail.create" : "Create similar process", "process.detail.actions": "Actions", - + "process.detail.delete.button": "Delete process", "process.detail.delete.header": "Delete process", @@ -3037,7 +3056,7 @@ "process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted", - + "profile.breadcrumbs": "Update Profile", From 70c6eac88d3de14cd70b4a9a83616f63785ebf57 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 15 Sep 2022 14:30:59 +0200 Subject: [PATCH 17/97] [CST-6753] Change google-analytics.service in order to use GoogleTagManager instead of GoogleAnalytics --- .../google-analytics.service.spec.ts | 25 +++++++++++-------- .../statistics/google-analytics.service.ts | 18 +++++++------ src/modules/app/server-app.module.ts | 5 ++-- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/app/statistics/google-analytics.service.spec.ts b/src/app/statistics/google-analytics.service.spec.ts index 0c6bc2bc51..24c5345260 100644 --- a/src/app/statistics/google-analytics.service.spec.ts +++ b/src/app/statistics/google-analytics.service.spec.ts @@ -1,20 +1,19 @@ import { GoogleAnalyticsService } from './google-analytics.service'; -import { Angulartics2GoogleAnalytics } from 'angulartics2'; +import { Angulartics2GoogleTagManager } from 'angulartics2'; import { ConfigurationDataService } from '../core/data/configuration-data.service'; -import { - createFailedRemoteDataObject$, - createSuccessfulRemoteDataObject$ -} from '../shared/remote-data.utils'; +import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; import { ConfigurationProperty } from '../core/shared/configuration-property.model'; describe('GoogleAnalyticsService', () => { const trackingIdProp = 'google.analytics.key'; const trackingIdTestValue = 'mock-tracking-id'; const innerHTMLTestValue = 'mock-script-inner-html'; + const srcTestValue = 'mock-script-src'; let service: GoogleAnalyticsService; - let angularticsSpy: Angulartics2GoogleAnalytics; + let angularticsSpy: Angulartics2GoogleTagManager; let configSpy: ConfigurationDataService; let scriptElementMock: any; + let srcSpy: any; let innerHTMLSpy: any; let bodyElementSpy: HTMLBodyElement; let documentSpy: Document; @@ -28,18 +27,21 @@ describe('GoogleAnalyticsService', () => { }); beforeEach(() => { - angularticsSpy = jasmine.createSpyObj('angulartics2GoogleAnalytics', [ + angularticsSpy = jasmine.createSpyObj('Angulartics2GoogleTagManager', [ 'startTracking', ]); configSpy = createConfigSuccessSpy(trackingIdTestValue); scriptElementMock = { + set src(newVal) { /* noop */ }, + get src() { return innerHTMLTestValue; }, set innerHTML(newVal) { /* noop */ }, - get innerHTML() { return innerHTMLTestValue; } + get innerHTML() { return srcTestValue; } }; innerHTMLSpy = spyOnProperty(scriptElementMock, 'innerHTML', 'set'); + srcSpy = spyOnProperty(scriptElementMock, 'src', 'set'); bodyElementSpy = jasmine.createSpyObj('body', { appendChild: scriptElementMock, @@ -106,19 +108,22 @@ describe('GoogleAnalyticsService', () => { describe('when the tracking id is non-empty', () => { it('should create a script tag whose innerHTML contains the tracking id', () => { service.addTrackingIdToPage(); - expect(documentSpy.createElement).toHaveBeenCalledTimes(1); + expect(documentSpy.createElement).toHaveBeenCalledTimes(2); expect(documentSpy.createElement).toHaveBeenCalledWith('script'); // sanity check expect(documentSpy.createElement('script')).toBe(scriptElementMock); + expect(srcSpy).toHaveBeenCalledTimes(1); + expect(srcSpy.calls.argsFor(0)[0]).toContain(trackingIdTestValue); + expect(innerHTMLSpy).toHaveBeenCalledTimes(1); expect(innerHTMLSpy.calls.argsFor(0)[0]).toContain(trackingIdTestValue); }); it('should add a script to the body', () => { service.addTrackingIdToPage(); - expect(bodyElementSpy.appendChild).toHaveBeenCalledTimes(1); + expect(bodyElementSpy.appendChild).toHaveBeenCalledTimes(2); }); it('should start tracking', () => { diff --git a/src/app/statistics/google-analytics.service.ts b/src/app/statistics/google-analytics.service.ts index 0b52f54c4f..6bdff53d52 100644 --- a/src/app/statistics/google-analytics.service.ts +++ b/src/app/statistics/google-analytics.service.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@angular/core'; -import { Angulartics2GoogleAnalytics } from 'angulartics2'; +import { Angulartics2GoogleTagManager } from 'angulartics2'; import { ConfigurationDataService } from '../core/data/configuration-data.service'; import { getFirstCompletedRemoteData } from '../core/shared/operators'; import { isEmpty } from '../shared/empty.util'; @@ -13,7 +13,8 @@ import { DOCUMENT } from '@angular/common'; export class GoogleAnalyticsService { constructor( - private angulartics: Angulartics2GoogleAnalytics, + // private angulartics: Angulartics2GoogleAnalytics, + private angulartics: Angulartics2GoogleTagManager, private configService: ConfigurationDataService, @Inject(DOCUMENT) private document: any, ) { } @@ -36,15 +37,16 @@ export class GoogleAnalyticsService { // make sure we received a tracking id if (isEmpty(trackingId)) { return; } - // add trackingId snippet to page + // add GTag snippet to page const keyScript = this.document.createElement('script'); - keyScript.innerHTML = `(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); - ga('create', '${trackingId}', 'auto');`; + keyScript.src = `https://www.googletagmanager.com/gtag/js?id=${trackingId}`; this.document.body.appendChild(keyScript); + const libScript = this.document.createElement('script'); + libScript.innerHTML = `window.dataLayer = window.dataLayer || [];function gtag(){window.dataLayer.push(arguments);} + gtag('js', new Date());gtag('config', '${trackingId}');`; + this.document.body.appendChild(libScript); + // start tracking this.angulartics.startTracking(); }); diff --git a/src/modules/app/server-app.module.ts b/src/modules/app/server-app.module.ts index 35fa050d6f..8565db3e23 100644 --- a/src/modules/app/server-app.module.ts +++ b/src/modules/app/server-app.module.ts @@ -6,8 +6,7 @@ import { ServerModule, ServerTransferStateModule } from '@angular/platform-serve import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { Angulartics2 } from 'angulartics2'; -import { Angulartics2GoogleAnalytics } from 'angulartics2'; +import { Angulartics2, Angulartics2GoogleTagManager } from 'angulartics2'; import { AppComponent } from '../../app/app.component'; @@ -60,7 +59,7 @@ export function createTranslateLoader(transferState: TransferState) { useClass: Angulartics2Mock }, { - provide: Angulartics2GoogleAnalytics, + provide: Angulartics2GoogleTagManager, useClass: AngularticsProviderMock }, { From 1df41deb8f071b58beaeb4ee88b3f1397d6851c0 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 15 Sep 2022 14:36:09 +0200 Subject: [PATCH 18/97] [CST-6753] Remove unused occurrences of GoogleAnalytics --- src/app/app.component.spec.ts | 4 +--- src/app/root/root.component.spec.ts | 2 -- src/app/root/root.component.ts | 2 -- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 8bec7edc80..422ead99e1 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,10 +1,9 @@ import { Store, StoreModule } from '@ngrx/store'; import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { CommonModule, DOCUMENT } from '@angular/common'; +import { CommonModule } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { Angulartics2GoogleAnalytics } from 'angulartics2'; // Load the implementations that should be tested import { AppComponent } from './app.component'; @@ -73,7 +72,6 @@ describe('App component', () => { providers: [ { provide: NativeWindowService, useValue: new NativeWindowRef() }, { provide: MetadataService, useValue: new MetadataServiceMock() }, - { provide: Angulartics2GoogleAnalytics, useValue: new AngularticsProviderMock() }, { provide: Angulartics2DSpace, useValue: new AngularticsProviderMock() }, { provide: AuthService, useValue: new AuthServiceMock() }, { provide: Router, useValue: new RouterMock() }, diff --git a/src/app/root/root.component.spec.ts b/src/app/root/root.component.spec.ts index 64a15a3087..504bc34e34 100644 --- a/src/app/root/root.component.spec.ts +++ b/src/app/root/root.component.spec.ts @@ -9,7 +9,6 @@ import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock'; import { NativeWindowRef, NativeWindowService } from '../core/services/window.service'; import { MetadataService } from '../core/metadata/metadata.service'; import { MetadataServiceMock } from '../shared/mocks/metadata-service.mock'; -import { Angulartics2GoogleAnalytics } from 'angulartics2'; import { AngularticsProviderMock } from '../shared/mocks/angulartics-provider.service.mock'; import { Angulartics2DSpace } from '../statistics/angulartics/dspace-provider'; import { AuthService } from '../core/auth/auth.service'; @@ -50,7 +49,6 @@ describe('RootComponent', () => { providers: [ { provide: NativeWindowService, useValue: new NativeWindowRef() }, { provide: MetadataService, useValue: new MetadataServiceMock() }, - { provide: Angulartics2GoogleAnalytics, useValue: new AngularticsProviderMock() }, { provide: Angulartics2DSpace, useValue: new AngularticsProviderMock() }, { provide: AuthService, useValue: new AuthServiceMock() }, { provide: Router, useValue: new RouterMock() }, diff --git a/src/app/root/root.component.ts b/src/app/root/root.component.ts index 3dc555919c..472ba440c9 100644 --- a/src/app/root/root.component.ts +++ b/src/app/root/root.component.ts @@ -5,7 +5,6 @@ import { Router } from '@angular/router'; import { combineLatest as combineLatestObservable, Observable, of } from 'rxjs'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; -import { Angulartics2GoogleAnalytics } from 'angulartics2'; import { MetadataService } from '../core/metadata/metadata.service'; import { HostWindowState } from '../shared/search/host-window.reducer'; @@ -51,7 +50,6 @@ export class RootComponent implements OnInit { private translate: TranslateService, private store: Store, private metadata: MetadataService, - private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics, private angulartics2DSpace: Angulartics2DSpace, private authService: AuthService, private router: Router, From fcae738db677d35ba92fe82b073377bff48235e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Jolin-Nicol?= Date: Thu, 15 Sep 2022 14:48:57 -0400 Subject: [PATCH 19/97] Fix for PR#1822 - Fix is in section-form-component.ts. Adjusted two equality checks for scope type which always returned false. --- src/app/core/eperson/models/workspaceitem.resource-type.ts | 3 +++ src/app/core/submission/models/workspaceitem.model.ts | 4 ++-- .../submission/sections/form/section-form.component.spec.ts | 4 ++-- src/app/submission/sections/form/section-form.component.ts | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 src/app/core/eperson/models/workspaceitem.resource-type.ts diff --git a/src/app/core/eperson/models/workspaceitem.resource-type.ts b/src/app/core/eperson/models/workspaceitem.resource-type.ts new file mode 100644 index 0000000000..e141d45a9f --- /dev/null +++ b/src/app/core/eperson/models/workspaceitem.resource-type.ts @@ -0,0 +1,3 @@ +import { ResourceType } from '../../shared/resource-type'; + +export const WORKSPACEITEM = new ResourceType('workspaceitem'); diff --git a/src/app/core/submission/models/workspaceitem.model.ts b/src/app/core/submission/models/workspaceitem.model.ts index 0bfacdb475..62f21cb2f3 100644 --- a/src/app/core/submission/models/workspaceitem.model.ts +++ b/src/app/core/submission/models/workspaceitem.model.ts @@ -2,7 +2,7 @@ import { deserializeAs, inheritSerialization } from 'cerialize'; import { inheritLinkAnnotations, typedObject } from '../../cache/builders/build-decorators'; import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; import { SubmissionObject } from './submission-object.model'; -import { ResourceType } from '../../shared/resource-type'; +import { WORKSPACEITEM } from '../../eperson/models/workspaceitem.resource-type'; /** * A model class for a WorkspaceItem. @@ -11,7 +11,7 @@ import { ResourceType } from '../../shared/resource-type'; @inheritSerialization(SubmissionObject) @inheritLinkAnnotations(SubmissionObject) export class WorkspaceItem extends SubmissionObject { - static type = new ResourceType('workspaceitem'); + static type = WORKSPACEITEM; /** * The universally unique identifier of this WorkspaceItem diff --git a/src/app/submission/sections/form/section-form.component.spec.ts b/src/app/submission/sections/form/section-form.component.spec.ts index beea55968c..c5205c070b 100644 --- a/src/app/submission/sections/form/section-form.component.spec.ts +++ b/src/app/submission/sections/form/section-form.component.spec.ts @@ -357,7 +357,7 @@ describe('SubmissionSectionFormComponent test suite', () => { describe('in workspace scope', () => { beforeEach(() => { // @ts-ignore - comp.submissionObject = { type: WorkspaceItem.type }; + comp.submissionObject = { type: WorkspaceItem.type.value }; }); it('should return true for unscoped fields', () => { @@ -376,7 +376,7 @@ describe('SubmissionSectionFormComponent test suite', () => { describe('in workflow scope', () => { beforeEach(() => { // @ts-ignore - comp.submissionObject = { type: WorkflowItem.type }; + comp.submissionObject = { type: WorkflowItem.type.value }; }); it('should return true when field is unscoped', () => { diff --git a/src/app/submission/sections/form/section-form.component.ts b/src/app/submission/sections/form/section-form.component.ts index 3fdc3cf486..17e44688a0 100644 --- a/src/app/submission/sections/form/section-form.component.ts +++ b/src/app/submission/sections/form/section-form.component.ts @@ -261,10 +261,10 @@ export class SubmissionSectionFormComponent extends SectionModelComponent { switch (scope) { case SubmissionScopeType.WorkspaceItem: { - return this.submissionObject.type === WorkspaceItem.type; + return (this.submissionObject as any).type === WorkspaceItem.type.value; } case SubmissionScopeType.WorkflowItem: { - return this.submissionObject.type === WorkflowItem.type; + return (this.submissionObject as any).type === WorkflowItem.type.value; } default: { return true; From f87b83ad8268ff94d9a4790453238ca94ebb2527 Mon Sep 17 00:00:00 2001 From: Abhishek Raval <100263510+abhishekd2t@users.noreply.github.com> Date: Sun, 18 Sep 2022 20:12:35 +0530 Subject: [PATCH 20/97] Add files via upload --- src/assets/i18n/hi.json5 | 6794 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 6794 insertions(+) create mode 100644 src/assets/i18n/hi.json5 diff --git a/src/assets/i18n/hi.json5 b/src/assets/i18n/hi.json5 new file mode 100644 index 0000000000..0d0476c7ea --- /dev/null +++ b/src/assets/i18n/hi.json5 @@ -0,0 +1,6794 @@ +{ + "401.help": { + "message": "आप इस पृष्ठ का प्रयोग करने की अनुमति नहीं हैं। होम पेज पर वापस जाने के लिए आप नीचे दिए गए बटन का उपयोग कर सकते हैं।" + }, + "401.link.home-page": { + "message": "मुझे होम पेज पर ले चलो" + }, + "401.unauthorized": { + "message": "अनधिकृत" + }, + "403.forbidden": { + "message": "वर्जित" + }, + "403.help": { + "message": "आपको इस पृष्ठ का अभिगमन करने की अनुमति नहीं है। होम पेज पर वापस जाने के लिए आप नीचे दिए गए बटन का उपयोग कर सकते हैं।" + }, + "403.link.home-page": { + "message": "मुझे होम पेज पर ले चलो" + }, + "404.help": { + "message": "आप जिस पेज की तलाश कर रहे हैं, वह हमें नहीं मिल रहा है। हो सकता है कि पृष्ठ को स्थानांतरित या हटा दिया गया हो। होम पेज पर वापस जाने के लिए आप नीचे दिए गए बटन का उपयोग कर सकते हैं।" + }, + "404.link.home-page": { + "message": "मुझे होम पेज पर ले जाएं" + }, + "404.page-not-found": { + "message": "पृष्ठ नहीं मिला" + }, + "500.help": { + "message": "रखरखाव डाउनटाइम या क्षमता समस्याओं के कारण सर्वर अस्थायी रूप से आपके अनुरोध को पूर्ण करने में असमर्थ है। कृपया बाद में पुन: प्रयास करें। " + }, + "500.link.home-page": { + "message": "मुझे होम पेज पर ले चलो" + }, + "500.page-internal-server-error": { + "message": "सेवा उप्लब्ध् नहीं है" + }, + "access-status.embargo.listelement.badge": { + "message": "प्रतिबंध" + }, + "access-status.metadata.only.listelement.badge": { + "message": "केवल मेटाडेटा" + }, + "access-status.open.access.listelement.badge": { + "message": "खुली पहुंच" + }, + "access-status.restricted.listelement.badge": { + "message": "प्रतिबंधित" + }, + "access-status.unknown.listelement.badge": { + "message": "अपरिचित" + }, + "admin.access-control.epeople.actions.delete": { + "message": "ई-व्यक्ति हटाएं" + }, + "admin.access-control.epeople.actions.impersonate": { + "message": "प्रतिरूपण ई-व्यक्ति" + }, + "admin.access-control.epeople.actions.reset": { + "message": "पासवर्ड रीसेट करें" + }, + "admin.access-control.epeople.actions.stop-impersonating": { + "message": "ई-व्यक्ति का रूप धारण करना बंद करें" + }, + "admin.access-control.epeople.breadcrumbs": { + "message": "ई लोग" + }, + "admin.access-control.epeople.button.add": { + "message": "ई-व्यक्ति जोड़ें" + }, + "admin.access-control.epeople.button.see-all": { + "message": "सब कुछ ब्राउज़ करें" + }, + "admin.access-control.epeople.form.canLogIn": { + "message": "लॉग इन कर सकते हैं" + }, + "admin.access-control.epeople.form.create": { + "message": "ई-व्यक्ति बनाएं" + }, + "admin.access-control.epeople.form.edit": { + "message": "ई-व्यक्ति संपादित करें" + }, + "admin.access-control.epeople.form.email": { + "message": "ईमेल" + }, + "admin.access-control.epeople.form.emailHint": { + "message": "वैध ई-मेल पता होना चाहिए" + }, + "admin.access-control.epeople.form.firstName": { + "message": "प्रथम नाम" + }, + "admin.access-control.epeople.form.goToGroups": { + "message": "समूहों में जोड़ें" + }, + "admin.access-control.epeople.form.groupsEPersonIsMemberOf": { + "message": "इन समूहों के सदस्य:" + }, + "admin.access-control.epeople.form.lastName": { + "message": "उपनाम" + }, + "admin.access-control.epeople.form.memberOfNoGroups": { + "message": "यह ई-व्यक्ति किसी भी समूह का सदस्य नहीं है" + }, + "admin.access-control.epeople.form.notification.created.failure": { + "message": "\"{{name}}\" ई-व्यक्ति बनाने में विफल" + }, + "admin.access-control.epeople.form.notification.created.failure.emailInUse": { + "message": "\"{{email}}\" ईमेल पहले से प्रयोग में होने के कारण \"{{name}}\" ई-व्यक्ति बनाना विफल हुआ। " + }, + "admin.access-control.epeople.form.notification.created.success": { + "message": "\"{{name}}\" ई-व्यक्ति सफलतापूर्वक बनाया गया " + }, + "admin.access-control.epeople.form.notification.deleted.failure": { + "message": "ई-व्यक्ति \"{{name}}\" को हटाने में विफल" + }, + "admin.access-control.epeople.form.notification.deleted.success": { + "message": "ई-व्यक्ति \"{{name}}\" को सफलतापूर्वक हटा दिया गया" + }, + "admin.access-control.epeople.form.notification.edited.failure": { + "message": "\"{{name}}\" ई-व्यक्ति संपादित करने में विफल" + }, + "admin.access-control.epeople.form.notification.edited.failure.emailInUse": { + "message": "ई-व्यक्ति \"{{name}}\", ईमेल \"{{email}}\" पहले से प्रयोग में संपादित करने में विफल।" + }, + "admin.access-control.epeople.form.notification.edited.success": { + "message": "ई-व्यक्ति \"{{name}}\" को सफलतापूर्वक संपादित किया गया" + }, + "admin.access-control.epeople.form.requireCertificate": { + "message": "प्रमाण पत्र की आवश्यकता है" + }, + "admin.access-control.epeople.form.return": { + "message": "वापस" + }, + "admin.access-control.epeople.form.table.collectionOrCommunity": { + "message": "संग्रह/समुदाय" + }, + "admin.access-control.epeople.form.table.id": { + "message": "पहचान" + }, + "admin.access-control.epeople.form.table.name": { + "message": "नाम" + }, + "admin.access-control.epeople.head": { + "message": "ई लोग" + }, + "admin.access-control.epeople.no-items": { + "message": "कोई ई-लोग दिखाने के लिए नहीं।" + }, + "admin.access-control.epeople.notification.deleted.failure": { + "message": "ई-व्यक्ति को हटाने में विफल: \"{{name}}\"" + }, + "admin.access-control.epeople.notification.deleted.success": { + "message": "ई-व्यक्ति को सफलतापूर्वक हटाया गया: \"{{name}}\"" + }, + "admin.access-control.epeople.search.button": { + "message": "खोजें" + }, + "admin.access-control.epeople.search.head": { + "message": "खोजें" + }, + "admin.access-control.epeople.search.placeholder": { + "message": "लोगों को खोजें..." + }, + "admin.access-control.epeople.search.scope.email": { + "message": "ईमेल (सटीक)" + }, + "admin.access-control.epeople.search.scope.metadata": { + "message": "मेटाडेटा" + }, + "admin.access-control.epeople.table.edit": { + "message": "संपादित करें" + }, + "admin.access-control.epeople.table.edit.buttons.edit": { + "message": "\"{{name}}\" संपादित करें" + }, + "admin.access-control.epeople.table.edit.buttons.edit-disabled": { + "message": "आप इस समूह को संपादित करने के लिए अधिकृत नहीं हैं" + }, + "admin.access-control.epeople.table.edit.buttons.remove": { + "message": "\"{{name}}\" मिटाएं" + }, + "admin.access-control.epeople.table.email": { + "message": "ईमेल (सटीक)" + }, + "admin.access-control.epeople.table.id": { + "message": "पहचान" + }, + "admin.access-control.epeople.table.name": { + "message": "नाम" + }, + "admin.access-control.epeople.title": { + "message": "ई लोग" + }, + "admin.access-control.groups.addGroup.breadcrumbs": { + "message": "नया समूह" + }, + "admin.access-control.groups.breadcrumbs": { + "message": "समूह" + }, + "admin.access-control.groups.button.add": { + "message": "समूह जोड़ें" + }, + "admin.access-control.groups.button.see-all": { + "message": "सब कुछ ब्राउज़ करें" + }, + "admin.access-control.groups.form.actions.delete": { + "message": "समूह हटाएं" + }, + "admin.access-control.groups.form.alert.permanent": { + "message": "यह समूह स्थायी है, इसलिए इसे संपादित या हटाया नहीं जा सकता है। आप अभी भी इस पृष्ठ का उपयोग करके समूह के सदस्यों को जोड़ और हटा सकते हैं।" + }, + "admin.access-control.groups.form.alert.workflowGroup": { + "message": "इस समूह को संशोधित या हटाया नहीं जा सकता क्योंकि \"{{name}}\" {{comcol}} प्रस्तुतीकरण और कार्यप्रवाह प्रक्रिया में एक भूमिका से संबंधित है। आप इसे हटाने के लिए {{comcol}} संपादन पृष्ठ पर \"assign roles\" टैब का प्रयोग कर सकते है। आप अभी भी इस पेज का उपयोग करके समूह के सदस्यों को जोड़ और हटा सकते हैं।" + }, + "admin.access-control.groups.form.delete-group.modal.cancel": { + "message": "रद्द करें" + }, + "admin.access-control.groups.form.delete-group.modal.confirm": { + "message": "हटाएं" + }, + "admin.access-control.groups.form.delete-group.modal.header": { + "message": "\"{{dsoName}}\" समूह हटाएं" + }, + "admin.access-control.groups.form.delete-group.modal.info": { + "message": "क्या आप वाकई \"{{dsoName}}\" समूह को हटाना चाहते हैं" + }, + "admin.access-control.groups.form.groupCommunity": { + "message": "समुदाय या संग्रह" + }, + "admin.access-control.groups.form.groupDescription": { + "message": "विवरण" + }, + "admin.access-control.groups.form.groupName": { + "message": "समूह का नाम" + }, + "admin.access-control.groups.form.head.create": { + "message": "समूह बनाएँ" + }, + "admin.access-control.groups.form.head.edit": { + "message": "समूह संपादित करें" + }, + "admin.access-control.groups.form.members-list.button.see-all": { + "message": "सब कुछ ब्राउज़ करें" + }, + "admin.access-control.groups.form.members-list.head": { + "message": "ई लोग" + }, + "admin.access-control.groups.form.members-list.headMembers": { + "message": "वर्तमान सदस्य" + }, + "admin.access-control.groups.form.members-list.no-items": { + "message": "उस खोज में कोई ई-लोग नहीं मिले" + }, + "admin.access-control.groups.form.members-list.no-members-yet": { + "message": "समूह में अभी तक कोई सदस्य नहीं है, सदस्य खोजें और जोड़ें।" + }, + "admin.access-control.groups.form.members-list.notification.failure.addMember": { + "message": "सदस्य जोड़ने में विफल: \"{{name}}\"" + }, + "admin.access-control.groups.form.members-list.notification.failure.deleteMember": { + "message": "सदस्य को हटाने में विफल: \"{{name}}\"" + }, + "admin.access-control.groups.form.members-list.notification.failure.noActiveGroup": { + "message": "पहले एक नाम प्रस्तुत करें, कोई वर्तमान सक्रिय समूह नहीं है।" + }, + "admin.access-control.groups.form.members-list.notification.success.addMember": { + "message": "\"{{name}}\" सदस्य सफलतापूर्वक जोड़ा गया" + }, + "admin.access-control.groups.form.members-list.notification.success.deleteMember": { + "message": "\"{{name}}\" सदस्य को सफलतापूर्वक हटाया गया" + }, + "admin.access-control.groups.form.members-list.search.button": { + "message": "खोजें" + }, + "admin.access-control.groups.form.members-list.search.head": { + "message": "ई-लोगों को जोड़ें" + }, + "admin.access-control.groups.form.members-list.search.scope.email": { + "message": "ईमेल (सटीक)" + }, + "admin.access-control.groups.form.members-list.search.scope.metadata": { + "message": "मेटाडेटा" + }, + "admin.access-control.groups.form.members-list.table.edit": { + "message": "हटाएं / जोड़ें" + }, + "admin.access-control.groups.form.members-list.table.edit.buttons.add": { + "message": "\"{{name}}\" नाम वाले सदस्य को जोड़ें" + }, + "admin.access-control.groups.form.members-list.table.edit.buttons.remove": { + "message": "\"{{name}}\" नाम वाले सदस्य को हटाएं" + }, + "admin.access-control.groups.form.members-list.table.email": { + "message": "ईमेल" + }, + "admin.access-control.groups.form.members-list.table.id": { + "message": "पहचान" + }, + "admin.access-control.groups.form.members-list.table.identity": { + "message": "पहचान" + }, + "admin.access-control.groups.form.members-list.table.name": { + "message": "नाम" + }, + "admin.access-control.groups.form.members-list.table.netid": { + "message": "NetID" + }, + "admin.access-control.groups.form.notification.created.failure": { + "message": "\"{{name}}\" समूह बनाने में विफल" + }, + "admin.access-control.groups.form.notification.created.failure.groupNameInUse": { + "message": "\"{{name}}\" नाम के साथ समूह बनाने में विफल, सुनिश्चित करें कि नाम पहले से उपयोग में नहीं है।" + }, + "admin.access-control.groups.form.notification.created.success": { + "message": "\"{{name}}\" समूह सफलतापूर्वक बनाया गया" + }, + "admin.access-control.groups.form.notification.deleted.failure.content": { + "message": "कारण: \"{{ cause }}\"" + }, + "admin.access-control.groups.form.notification.deleted.failure.title": { + "message": "\"{{ name }}\" समूह को हटाने में विफल" + }, + "admin.access-control.groups.form.notification.deleted.success": { + "message": "\"{{ name }}\" समूह को सफलतापूर्वक हटाया गया" + }, + "admin.access-control.groups.form.notification.edited.failure": { + "message": "\"{{name}}\" समूह को संपादित करने में विफल" + }, + "admin.access-control.groups.form.notification.edited.failure.groupNameInUse": { + "message": "\"{{name}}\" नाम पहले से प्रयोग में है!" + }, + "admin.access-control.groups.form.notification.edited.success": { + "message": "\"{{name}}\" समूह को सफलतापूर्वक संपादित किया गया" + }, + "admin.access-control.groups.form.return": { + "message": "वापस" + }, + "admin.access-control.groups.form.subgroups-list.button.see-all": { + "message": "सभी ब्राउज़ करें" + }, + "admin.access-control.groups.form.subgroups-list.head": { + "message": "समूह" + }, + "admin.access-control.groups.form.subgroups-list.headSubgroups": { + "message": "वर्तमान उपसमूह" + }, + "admin.access-control.groups.form.subgroups-list.no-items": { + "message": "इसके नाम से कोई समूह नहीं मिला या यह UUID के रूप में नहीं है" + }, + "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": { + "message": "समूह में अभी तक कोई उपसमूह नहीं है।" + }, + "admin.access-control.groups.form.subgroups-list.notification.failure": { + "message": "कुछ गलत हुआ: \"{{cause}}\"" + }, + "admin.access-control.groups.form.subgroups-list.notification.failure.addSubgroup": { + "message": "उपसमूह जोड़ने में विफल: \"{{name}}\"" + }, + "admin.access-control.groups.form.subgroups-list.notification.failure.deleteSubgroup": { + "message": "\"{{name}}\" उपसमूह को हटाने में विफल" + }, + "admin.access-control.groups.form.subgroups-list.notification.failure.noActiveGroup": { + "message": "कोई वर्तमान सक्रिय समूह नहीं है, पहले एक नाम प्रस्तुत करें।" + }, + "admin.access-control.groups.form.subgroups-list.notification.failure.subgroupToAddIsActiveGroup": { + "message": "यह वर्तमान समूह है, जोड़ा नहीं जा सकता।" + }, + "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": { + "message": "उपसमूह सफलतापूर्वक जोड़ा गया: \"{{name}}\"" + }, + "admin.access-control.groups.form.subgroups-list.notification.success.deleteSubgroup": { + "message": "\"{{name}}\" उपसमूह को सफलतापूर्वक हटाया गया" + }, + "admin.access-control.groups.form.subgroups-list.search.button": { + "message": "खोजें" + }, + "admin.access-control.groups.form.subgroups-list.search.head": { + "message": "उपसमूह जोड़ें" + }, + "admin.access-control.groups.form.subgroups-list.table.collectionOrCommunity": { + "message": "संग्रह/समुदाय" + }, + "admin.access-control.groups.form.subgroups-list.table.edit": { + "message": "हटाएं / जोड़ें" + }, + "admin.access-control.groups.form.subgroups-list.table.edit.buttons.add": { + "message": "\"{{name}}\" नाम से उपसमूह जोड़ें" + }, + "admin.access-control.groups.form.subgroups-list.table.edit.buttons.remove": { + "message": "\"{{name}}\" नाम से उपसमूह हटाएं" + }, + "admin.access-control.groups.form.subgroups-list.table.edit.currentGroup": { + "message": "वर्तमान समूह" + }, + "admin.access-control.groups.form.subgroups-list.table.id": { + "message": "पहचान" + }, + "admin.access-control.groups.form.subgroups-list.table.name": { + "message": "नाम" + }, + "admin.access-control.groups.head": { + "message": "समूह" + }, + "admin.access-control.groups.no-items": { + "message": "इसके नाम से कोई समूह नहीं मिला या यह UUID के रूप में नहीं है" + }, + "admin.access-control.groups.notification.deleted.failure.content": { + "message": "कारण: \"{{cause}}\"" + }, + "admin.access-control.groups.notification.deleted.failure.title": { + "message": "\"{{name}}\" समूह को हटाने में विफल" + }, + "admin.access-control.groups.notification.deleted.success": { + "message": "समूह \"{{name}}\" को सफलतापूर्वक हटाया गया" + }, + "admin.access-control.groups.search.button": { + "message": "खोजें" + }, + "admin.access-control.groups.search.head": { + "message": "समूह खोजें" + }, + "admin.access-control.groups.search.placeholder": { + "message": "समूह खोजें..." + }, + "admin.access-control.groups.singleGroup.breadcrumbs": { + "message": "समूह संपादित करें" + }, + "admin.access-control.groups.table.collectionOrCommunity": { + "message": "संग्रह/समुदाय" + }, + "admin.access-control.groups.table.edit": { + "message": "संपादित करें" + }, + "admin.access-control.groups.table.edit.buttons.edit": { + "message": "\"{{name}}\" संपादित करें" + }, + "admin.access-control.groups.table.edit.buttons.remove": { + "message": "\"{{name}}\" हटाएं" + }, + "admin.access-control.groups.table.id": { + "message": "पहचान" + }, + "admin.access-control.groups.table.members": { + "message": "सदस्य" + }, + "admin.access-control.groups.table.name": { + "message": "नाम" + }, + "admin.access-control.groups.title": { + "message": "समूह" + }, + "admin.access-control.groups.title.addGroup": { + "message": "नया समूह" + }, + "admin.access-control.groups.title.singleGroup": { + "message": "समूह संपादित करें" + }, + "admin.curation-tasks.breadcrumbs": { + "message": "प्रणाली क्यूरेशन कार्य" + }, + "admin.curation-tasks.header": { + "message": "प्रणाली क्यूरेशन कार्य" + }, + "admin.curation-tasks.title": { + "message": "प्रणाली क्यूरेशन कार्य" + }, + "admin.metadata-import.breadcrumbs": { + "message": "मेटाडेटा आयात करें" + }, + "admin.metadata-import.page.button.proceed": { + "message": "आगे बढ़ें" + }, + "admin.metadata-import.page.button.return": { + "message": "वापस" + }, + "admin.metadata-import.page.dropMsg": { + "message": "आयात करने के लिए मेटाडेटा CSV छोड़ें" + }, + "admin.metadata-import.page.dropMsgReplace": { + "message": "आयात करने के लिए मेटाडेटा CSV को बदलने के लिए ड्रॉप करें" + }, + "admin.metadata-import.page.error.addFile": { + "message": "पहले फ़ाइल का चयन करें!" + }, + "admin.metadata-import.page.header": { + "message": "मेटाडेटा आयात करें" + }, + "admin.metadata-import.page.help": { + "message": "आप उन CSV फ़ाइलों को छोड़ या ब्राउज़ कर सकते हैं जिनमें फ़ाइलों पर बैच मेटाडेटा संचालन शामिल हैं" + }, + "admin.metadata-import.page.validateOnly": { + "message": "केवल मान्य करें" + }, + "admin.metadata-import.page.validateOnly.hint": { + "message": "चुनी गयी CSV फाइल को उप्लोअडिंग उपरांत पुष्टिकृत किया जाएगा। आपको पाए गए परिवर्तनों की रिपोर्ट प्राप्त होगी, लेकिन कोई भी परिवर्तन सहेजा नहीं जाएगा।" + }, + "admin.metadata-import.title": { + "message": "मेटाडेटा आयात करें" + }, + "admin.registries.bitstream-formats.breadcrumbs": { + "message": "प्रारूप रजिस्ट्री" + }, + "admin.registries.bitstream-formats.create.breadcrumbs": { + "message": "बिटस्ट्रीम प्रारूप" + }, + "admin.registries.bitstream-formats.create.failure.content": { + "message": "नया बिटस्ट्रीम प्रारूप बनाते समय एक त्रुटि हुई।" + }, + "admin.registries.bitstream-formats.create.failure.head": { + "message": "असफलता" + }, + "admin.registries.bitstream-formats.create.head": { + "message": "बिटस्ट्रीम प्रारूप बनाएं" + }, + "admin.registries.bitstream-formats.create.new": { + "message": "एक नया बिटस्ट्रीम प्रारूप जोड़ें" + }, + "admin.registries.bitstream-formats.create.success.content": { + "message": "नया बिटस्ट्रीम स्वरूप सफलतापूर्वक बनाया गया।" + }, + "admin.registries.bitstream-formats.create.success.head": { + "message": "सफलता" + }, + "admin.registries.bitstream-formats.delete.failure.amount": { + "message": "{{ amount }} प्रारूप (प्रारूपों) को निकालने में विफल" + }, + "admin.registries.bitstream-formats.delete.failure.head": { + "message": "असफलता" + }, + "admin.registries.bitstream-formats.delete.success.amount": { + "message": "{{ amount}} प्रारूप (प्रारूपों) को सफलतापूर्वक हटा दिया गया हैं|" + }, + "admin.registries.bitstream-formats.delete.success.head": { + "message": "सफलता" + }, + "admin.registries.bitstream-formats.description": { + "message": "बिटस्ट्रीम प्रारूपों की यह सूची ज्ञात स्वरूपों और उनके समर्थन स्तर के बारे में जानकारी प्रदान करती है।" + }, + "admin.registries.bitstream-formats.edit.breadcrumbs": { + "message": "बिटस्ट्रीम प्रारूप" + }, + "admin.registries.bitstream-formats.edit.description.hint": { + "message": "" + }, + "admin.registries.bitstream-formats.edit.description.label": { + "message": "विवरण" + }, + "admin.registries.bitstream-formats.edit.extensions.hint": { + "message": "एक्सटेंशन का उपयोग अपलोड की गई फ़ाइलों के प्रारूप को स्वचालित रूप से पहचानने के लिए किया जाता है। आप प्रत्येक प्रारूप के लिए कई एक्सटेंशन दर्ज कर सकते हैं।" + }, + "admin.registries.bitstream-formats.edit.extensions.label": { + "message": "फाइल एक्सटेंशन" + }, + "admin.registries.bitstream-formats.edit.extensions.placeholder": { + "message": "बिंदु के बिना फ़ाइल एक्सटेंशन दर्ज करें" + }, + "admin.registries.bitstream-formats.edit.failure.content": { + "message": "बिटस्ट्रीम प्रारूप को संपादित करते समय एक त्रुटि हुई।" + }, + "admin.registries.bitstream-formats.edit.failure.head": { + "message": "असफलता" + }, + "admin.registries.bitstream-formats.edit.head": { + "message": "बिटस्ट्रीम प्रारूप: {{ format }}" + }, + "admin.registries.bitstream-formats.edit.internal.hint": { + "message": "आंतरिक के रूप में चिह्नित प्रारूप उपयोगकर्ता से छिपे हुए हैं, और प्रशासनिक उद्देश्यों के लिए उपयोग किए जाते हैं।" + }, + "admin.registries.bitstream-formats.edit.internal.label": { + "message": "आंतरिक" + }, + "admin.registries.bitstream-formats.edit.mimetype.hint": { + "message": "इस प्रारूप से जुड़े MIME प्रकार का अद्वितीय होना आवश्यक नहीं है।" + }, + "admin.registries.bitstream-formats.edit.mimetype.label": { + "message": "माइम (MIME) प्रकार" + }, + "admin.registries.bitstream-formats.edit.shortDescription.hint": { + "message": "इस प्रारूप के लिए एक अनूठा नाम, (जैसे माइक्रोसॉफ्ट वर्ड एक्सपी या माइक्रोसॉफ्ट वर्ड 2000)" + }, + "admin.registries.bitstream-formats.edit.shortDescription.label": { + "message": "नाम" + }, + "admin.registries.bitstream-formats.edit.success.content": { + "message": "बिटस्ट्रीम प्रारूप सफलतापूर्वक संपादित किया गया।" + }, + "admin.registries.bitstream-formats.edit.success.head": { + "message": "सफलता" + }, + "admin.registries.bitstream-formats.edit.supportLevel.hint": { + "message": "इस प्रारूप के लिए आपकी संस्था द्वारा दिए गए समर्थन का स्तर।" + }, + "admin.registries.bitstream-formats.edit.supportLevel.label": { + "message": "समर्थन स्तर" + }, + "admin.registries.bitstream-formats.head": { + "message": "बिटस्ट्रीम प्रारूप रजिस्ट्री" + }, + "admin.registries.bitstream-formats.no-items": { + "message": "दिखाने के लिए कोई बिटस्ट्रीम प्रारूप नहीं।" + }, + "admin.registries.bitstream-formats.table.delete": { + "message": "चयनित हटाएं" + }, + "admin.registries.bitstream-formats.table.deselect-all": { + "message": "सभी को अचयनित करें" + }, + "admin.registries.bitstream-formats.table.internal": { + "message": "आंतरिक" + }, + "admin.registries.bitstream-formats.table.mimetype": { + "message": "माइम (MIME) प्रकार" + }, + "admin.registries.bitstream-formats.table.name": { + "message": "नाम" + }, + "admin.registries.bitstream-formats.table.return": { + "message": "पीछे" + }, + "admin.registries.bitstream-formats.table.supportLevel.head": { + "message": "समर्थन स्तर" + }, + "admin.registries.bitstream-formats.table.supportLevel.KNOWN": { + "message": "परिचित" + }, + "admin.registries.bitstream-formats.table.supportLevel.SUPPORTED": { + "message": "समर्थित" + }, + "admin.registries.bitstream-formats.table.supportLevel.UNKNOWN": { + "message": "अज्ञात" + }, + "admin.registries.bitstream-formats.title": { + "message": "बिटस्ट्रीम प्रारूप रजिस्ट्री" + }, + "admin.registries.metadata.breadcrumbs": { + "message": "मेटाडेटा रजिस्ट्री" + }, + "admin.registries.metadata.description": { + "message": "मेटाडेटा रजिस्ट्री संग्रहालय में उपलब्ध सभी मेटाडेटा फ़ील्ड की एक सूची रखता है। इन क्षेत्रों को कई स्कीमाओं में विभाजित किया जा सकता है। हालांकि, डीस्पेस को योग्य डबलिन कोर स्कीमा की आवश्यकता है।" + }, + "admin.registries.metadata.form.create": { + "message": "मेटाडेटा स्कीमा बनाएं" + }, + "admin.registries.metadata.form.edit": { + "message": "मेटाडेटा स्कीमा संपादित करें" + }, + "admin.registries.metadata.form.name": { + "message": "नाम" + }, + "admin.registries.metadata.form.namespace": { + "message": "नाम स्थान" + }, + "admin.registries.metadata.head": { + "message": "मेटाडेटा रजिस्ट्री" + }, + "admin.registries.metadata.schemas.no-items": { + "message": "दिखाने के लिए कोई मेटाडेटा स्कीमा नहीं है।" + }, + "admin.registries.metadata.schemas.table.delete": { + "message": "चयनित हटाएं" + }, + "admin.registries.metadata.schemas.table.id": { + "message": "पहचान" + }, + "admin.registries.metadata.schemas.table.name": { + "message": "नाम" + }, + "admin.registries.metadata.schemas.table.namespace": { + "message": "नाम स्थान" + }, + "admin.registries.metadata.title": { + "message": "मेटाडेटा रजिस्ट्री" + }, + "admin.registries.schema.breadcrumbs": { + "message": "मेटाडेटा स्कीमा" + }, + "admin.registries.schema.description": { + "message": "यह \"{{namespace}}\" के लिए मेटाडेटा स्कीमा है।" + }, + "admin.registries.schema.fields.head": { + "message": "स्कीमा मेटाडेटा फ़ील्ड" + }, + "admin.registries.schema.fields.no-items": { + "message": "दिखाने के लिए कोई मेटाडेटा फ़ील्ड नहीं है|" + }, + "admin.registries.schema.fields.table.delete": { + "message": "चयनित हटाएं" + }, + "admin.registries.schema.fields.table.field": { + "message": " फील्ड" + }, + "admin.registries.schema.fields.table.scopenote": { + "message": "कार्यक्षेत्र नोट" + }, + "admin.registries.schema.form.create": { + "message": "मेटाडेटा फ़ील्ड बनाएं" + }, + "admin.registries.schema.form.edit": { + "message": "मेटाडेटा फ़ील्ड संपादित करें" + }, + "admin.registries.schema.form.element": { + "message": "तत्व" + }, + "admin.registries.schema.form.qualifier": { + "message": "क्वालीफायर" + }, + "admin.registries.schema.form.scopenote": { + "message": "कार्यक्षेत्र नोट" + }, + "admin.registries.schema.head": { + "message": "मेटाडेटा स्कीमा" + }, + "admin.registries.schema.notification.created": { + "message": "\"{{prefix}}\" मेटाडेटा स्कीमा सफलतापूर्वक बनाया गया" + }, + "admin.registries.schema.notification.deleted.failure": { + "message": "{{amount}} मेटाडेटा स्कीमा हटाने में विफल" + }, + "admin.registries.schema.notification.deleted.success": { + "message": "{{amount}} मेटाडेटा स्कीमा सफलतापूर्वक हटा दिए गए" + }, + "admin.registries.schema.notification.edited": { + "message": "\"{{prefix}}\" मेटाडेटा स्कीमा को सफलतापूर्वक संपादित किया गया" + }, + "admin.registries.schema.notification.failure": { + "message": "त्रुटि" + }, + "admin.registries.schema.notification.field.created": { + "message": "\"{{field}}\" मेटाडेटा फ़ील्ड को सफलतापूर्वक बनाया गया" + }, + "admin.registries.schema.notification.field.deleted.failure": { + "message": "{{amount}} मेटाडेटा फ़ील्ड हटाने में विफल" + }, + "admin.registries.schema.notification.field.deleted.success": { + "message": "{{amount}} मेटाडेटा फ़ील्ड को सफलतापूर्वक हटाया गया" + }, + "admin.registries.schema.notification.field.edited": { + "message": "\"{{field}}\" मेटाडेटा फ़ील्ड को सफलतापूर्वक संपादित किया गया" + }, + "admin.registries.schema.notification.success": { + "message": "सफलता" + }, + "admin.registries.schema.return": { + "message": "वापस" + }, + "admin.registries.schema.title": { + "message": "मेटाडेटा स्कीमा रजिस्ट्री" + }, + "admin.search.breadcrumbs": { + "message": "प्रशासनिक खोज" + }, + "admin.search.collection.edit": { + "message": "संपादित करें" + }, + "admin.search.community.edit": { + "message": "संपादित करें" + }, + "admin.search.item.delete": { + "message": "हटाएं" + }, + "admin.search.item.edit": { + "message": "संपादित करें" + }, + "admin.search.item.make-private": { + "message": "खोजे न जाने योग्य बनाएं" + }, + "admin.search.item.make-public": { + "message": "खोजने योग्य बनाएं" + }, + "admin.search.item.move": { + "message": "स्थान परिवर्तन" + }, + "admin.search.item.reinstate": { + "message": "पुनर्स्थापित करें" + }, + "admin.search.item.withdraw": { + "message": "वापस लेना" + }, + "admin.search.title": { + "message": "प्रशासनिक खोज" + }, + "admin.workflow.breadcrumbs": { + "message": "कार्यप्रवाह व्यवस्थापित करें" + }, + "admin.workflow.item.delete": { + "message": "हटाएं" + }, + "admin.workflow.item.send-back": { + "message": "वापस भेजे" + }, + "admin.workflow.item.workflow": { + "message": "कार्यप्रवाह" + }, + "admin.workflow.title": { + "message": "कार्यप्रवाह व्यवस्थापित करें" + }, + "administrativeView.search.results.head": { + "message": "प्रशासनिक खोज" + }, + "auth.errors.invalid-user": { + "message": "अमान्य ई - मेल पता अथवा पासवर्ड।" + }, + "auth.messages.expired": { + "message": "आपका सत्र समाप्त हो गया है। कृपया फिर लॉगिन करें।" + }, + "auth.messages.token-refresh-failed": { + "message": "आपका सत्र टोकन रीफ़्रेश करना विफल रहा। कृपया फिर लॉगिन करें।" + }, + "bitstream-request-a-copy.alert.canDownload1": { + "message": "आपके पास पहले से ही इस फ़ाइल तक पहुंच है। अगर आप फ़ाइल डाउनलोड करना चाहते हैं, तो क्लिक करें" + }, + "bitstream-request-a-copy.alert.canDownload2": { + "message": "यहां" + }, + "bitstream-request-a-copy.allfiles.label": { + "message": "फ़ाइलें" + }, + "bitstream-request-a-copy.email.error": { + "message": "कृपया वैध ई - मेल एड्रेस डालें।" + }, + "bitstream-request-a-copy.email.hint": { + "message": "इस ईमेल पते का उपयोग फ़ाइल भेजने के लिए किया जाता है।" + }, + "bitstream-request-a-copy.email.label": { + "message": "आपका ईमेल पता *" + }, + "bitstream-request-a-copy.files-all-false.label": { + "message": "केवल अनुरोधित फ़ाइल" + }, + "bitstream-request-a-copy.files-all-true.label": { + "message": "सभी फ़ाइलें (इस आइटम की) प्रतिबंधित पहुंच में हैं" + }, + "bitstream-request-a-copy.header": { + "message": "फ़ाइल की एक प्रति का अनुरोध करें" + }, + "bitstream-request-a-copy.intro": { + "message": "निम्नलिखित मद के लिए एक प्रति का अनुरोध करने के लिए निम्नलिखित जानकारी दर्ज करें:" + }, + "bitstream-request-a-copy.intro.bitstream.one": { + "message": "Requesting the following file: " + }, + "bitstream-request-a-copy.intro.bitstream.other": { + "message": null + }, + "bitstream-request-a-copy.intro.bitstream.zero": { + "message": null + }, + "bitstream-request-a-copy.intro.bitstream.all": { + "message": "सभी फाइलों का अनुरोध।" + }, + "bitstream-request-a-copy.message.label": { + "message": "संदेश" + }, + "bitstream-request-a-copy.name.error": { + "message": "नाम आवश्यक है" + }, + "bitstream-request-a-copy.name.label": { + "message": "नाम *" + }, + "bitstream-request-a-copy.return": { + "message": "वापस" + }, + "bitstream-request-a-copy.submit": { + "message": "प्रति अनुरोध " + }, + "bitstream-request-a-copy.submit.error": { + "message": "आइटम अनुरोध प्रस्तुत करने में कोई गड़बड़ी हुई|" + }, + "bitstream-request-a-copy.submit.success": { + "message": "आइटम अनुरोध सफलतापूर्वक प्रस्तुत किया गया। " + }, + "bitstream.download.page": { + "message": "अब {{bitstream}} डाउनलोड हो रहा है..." + }, + "bitstream.download.page.back": { + "message": "वापस" + }, + "bitstream.edit.authorizations.link": { + "message": "बिटस्ट्रीम की नीतियां संपादित करें" + }, + "bitstream.edit.authorizations.title": { + "message": "बिटस्ट्रीम की नीतियां संपादित करें" + }, + "bitstream.edit.bitstream": { + "message": "बिटस्ट्रीम: " + }, + "bitstream.edit.form.description.hint": { + "message": "वैकल्पिक रूप से, फ़ाइल का संक्षिप्त विवरण प्रदान करें, उदाहरण के लिए \"मुख्य लेख\" या \"डेटा रीडिंग का प्रयोग करें\"।" + }, + "bitstream.edit.form.description.label": { + "message": "विवरण" + }, + "bitstream.edit.form.embargo.hint": { + "message": "पहला दिन जब से प्रवेश की अनुमति है। इस फॉर्म पर इस तिथि को संशोधित नहीं किया जा सकता है। बिटस्ट्रीम के लिए एक प्रतिबंध तिथि निर्धारित करने के लिए, आइटम स्थिति टैब पर जाएं, प्राधिकरण... पर क्लिक करें, बिटस्ट्रीम की READ नीति बनाएं या संपादित करें, और वांछित के रूप में प्रारंभ तिथि सेट करें।" + }, + "bitstream.edit.form.embargo.label": { + "message": "विशिष्ट तिथि तक प्रतिबंध" + }, + "bitstream.edit.form.fileName.hint": { + "message": "बिटस्ट्रीम के लिए फ़ाइल नाम बदलें। ध्यान दें कि यह प्रदर्शन बिटस्ट्रीम URL को बदल देगा, लेकिन पुराने लिंक तब तक हल होंगे जब तक अनुक्रम आईडी नहीं बदलेगा।" + }, + "bitstream.edit.form.fileName.label": { + "message": "फ़ाइल का नाम" + }, + "bitstream.edit.form.iiifHeight.hint": { + "message": "कैनवास की चौड़ाई आमतौर पर छवि की चौड़ाई से मेल खाना चाहिए।" + }, + "bitstream.edit.form.iiifHeight.label": { + "message": "IIIF Canvas Height" + }, + "bitstream.edit.form.iiifLabel.hint": { + "message": "इस छवि के लिए कैनवास लेबल। यदि प्रदान नहीं किया गया है तो डिफ़ॉल्ट लेबल का उपयोग किया जाएगा।" + }, + "bitstream.edit.form.iiifLabel.label": { + "message": "आईआईआईएफ लेबल" + }, + "bitstream.edit.form.iiifToc.hint": { + "message": "यहां शब्द जोड़ने से यह सामग्री श्रेणी की एक नई तालिका की शुरुआत होगी।" + }, + "bitstream.edit.form.iiifToc.label": { + "message": "आईआईआईएफ सामग्री तालिका" + }, + "bitstream.edit.form.iiifWidth.hint": { + "message": "कैनवास की चौड़ाई आमतौर पर छवि की चौड़ाई से मेल खाना चाहिए।" + }, + "bitstream.edit.form.iiifWidth.label": { + "message": "आईआईआईएफ कैनवास चौड़ाई" + }, + "bitstream.edit.form.newFormat.hint": { + "message": "फ़ाइल बनाने के लिए आपके द्वारा उपयोग किया जाने वाला एप्लिकेशन, और संस्करण संख्या (उदाहरण के लिए, \"ACMESoft SuperApp संस्करण 1.5\")।" + }, + "bitstream.edit.form.newFormat.label": { + "message": "नए प्रारूप का वर्णन करें" + }, + "bitstream.edit.form.primaryBitstream.label": { + "message": "प्राथमिक बिटस्ट्रीम" + }, + "bitstream.edit.form.selectedFormat.hint": { + "message": "यदि प्रारूप उपरोक्त सूची में नहीं है, तो उपरोक्त \"प्रारूप सूची में नहीं है\" चुनें और \"नए प्रारूप का वर्णन करें\" के तहत इसका वर्णन करें।" + }, + "bitstream.edit.form.selectedFormat.label": { + "message": "चयनित प्रारूप" + }, + "bitstream.edit.form.selectedFormat.unknown": { + "message": "प्रारूप सूची में नहीं है" + }, + "bitstream.edit.notifications.error.format.title": { + "message": "बिटस्ट्रीम के प्रारूप को सहेजते समय एक त्रुटि हुई" + }, + "bitstream.edit.notifications.saved.content": { + "message": "इस बिटस्ट्रीम में आपके परिवर्तन सहेजे गए।" + }, + "bitstream.edit.notifications.saved.title": { + "message": "बिटस्ट्रीम सहेजा गया" + }, + "bitstream.edit.return": { + "message": "वापस" + }, + "bitstream.edit.title": { + "message": "बिटस्ट्रीम संपादित करें" + }, + "browse.back.all-results": { + "message": "सभी ब्राउज़ परिणाम" + }, + "browse.comcol.by.author": { + "message": "लेखक द्वारा" + }, + "browse.comcol.by.dateissued": { + "message": "जारी करने की तिथि के द्वारा" + }, + "browse.comcol.by.subject": { + "message": "विषय द्वारा" + }, + "browse.comcol.by.title": { + "message": "शीर्षक के द्वारा" + }, + "browse.comcol.head": { + "message": "ब्राउज़" + }, + "browse.empty": { + "message": "दिखाने के लिए कोई आइटम नहीं है।" + }, + "browse.metadata.author": { + "message": "लेखक" + }, + "browse.metadata.author.breadcrumbs": { + "message": "लेखक द्वारा ब्राउज़ करें" + }, + "browse.metadata.dateissued": { + "message": "जारी करने की तिथि" + }, + "browse.metadata.dateissued.breadcrumbs": { + "message": "तिथि द्वारा ब्राउज़ करें" + }, + "browse.metadata.subject": { + "message": "विषय" + }, + "browse.metadata.subject.breadcrumbs": { + "message": "विषय द्वारा ब्राउज़ करें" + }, + "browse.metadata.title": { + "message": "शीर्षक" + }, + "browse.metadata.title.breadcrumbs": { + "message": "शीर्षक द्वारा ब्राउज़ करें" + }, + "browse.startsWith": { + "message": ", {{ startWith }} से शुरू होता है" + }, + "browse.startsWith.choose_start": { + "message": "(प्रारंभ चुनें)" + }, + "browse.startsWith.choose_year": { + "message": "(वर्ष चुनें)" + }, + "browse.startsWith.choose_year.label": { + "message": "जारी करने का वर्ष चुने" + }, + "browse.startsWith.jump": { + "message": "साल या महीने के हिसाब से नतीजे फ़िल्टर करें" + }, + "browse.startsWith.months.april": { + "message": "अप्रैल" + }, + "browse.startsWith.months.august": { + "message": "अगस्त" + }, + "browse.startsWith.months.december": { + "message": "दिसंबर" + }, + "browse.startsWith.months.february": { + "message": "फ़रवरी" + }, + "browse.startsWith.months.january": { + "message": "जनवरी" + }, + "browse.startsWith.months.july": { + "message": "जुलाई" + }, + "browse.startsWith.months.june": { + "message": "जून" + }, + "browse.startsWith.months.march": { + "message": "मार्च" + }, + "browse.startsWith.months.may": { + "message": "मई" + }, + "browse.startsWith.months.none": { + "message": "(महीना चुनें)" + }, + "browse.startsWith.months.none.label": { + "message": "प्रकाशन माह चुनें" + }, + "browse.startsWith.months.november": { + "message": "नवंबर" + }, + "browse.startsWith.months.october": { + "message": "अक्टूबर" + }, + "browse.startsWith.months.september": { + "message": "सितंबर" + }, + "browse.startsWith.submit": { + "message": "ब्राउज़" + }, + "browse.startsWith.type_date": { + "message": "दिनांक के अनुसार परिणाम फ़िल्टर करें" + }, + "browse.startsWith.type_date.label": { + "message": "या एक तिथि (वर्ष-माह) टाइप करें और ब्राउज़ बटन पर क्लिक करें" + }, + "browse.startsWith.type_text": { + "message": "पहले कुछ अक्षर लिखकर परिणाम फ़िल्टर करें" + }, + "browse.title": { + "message": "{{ collection }} को {{ field }}{{ startsWith }} {{ value }} द्वारा ब्राउज़ करें\n" + }, + "browse.title.page": { + "message": "{{ collection }} को {{ field }} {{ value }} द्वारा ब्राउज़ करना" + }, + "chips.remove": { + "message": "चिप निकालें" + }, + "collection.create.head": { + "message": "एक संग्रह बनाएं" + }, + "collection.create.notifications.success": { + "message": "संग्रह सफलतापूर्वक बनाया गया" + }, + "collection.create.sub-head": { + "message": "{{ parent }} समुदाय के लिए एक संग्रह बनाएं" + }, + "collection.curate.header": { + "message": "क्यूरेट संग्रह: {{collection}}" + }, + "collection.delete.cancel": { + "message": "रद्द करें" + }, + "collection.delete.confirm": { + "message": "पुष्टि करें" + }, + "collection.delete.head": { + "message": "संग्रह हटाएं" + }, + "collection.delete.notification.fail": { + "message": "संग्रह हटाया नहीं जा सका" + }, + "collection.delete.notification.success": { + "message": "संग्रह को सफलतापूर्वक हटाया गया" + }, + "collection.delete.processing": { + "message": "हटाया जा रहा है" + }, + "collection.delete.text": { + "message": "क्या आप वाकई \"{{ dso }}\" संग्रह हटाना चाहते हैं" + }, + "collection.edit.breadcrumbs": { + "message": "संग्रह संपादित करें" + }, + "collection.edit.delete": { + "message": "इस संग्रह को हटाएं" + }, + "collection.edit.head": { + "message": "संग्रह संपादित करें" + }, + "collection.edit.item-mapper.cancel": { + "message": "रद्द करें" + }, + "collection.edit.item-mapper.collection": { + "message": "संग्रह: \"{{name}}\"" + }, + "collection.edit.item-mapper.confirm": { + "message": "चयनित आइटम मैप करें" + }, + "collection.edit.item-mapper.description": { + "message": "यह आइटम मैपर उपकरण है जो संग्रह प्रशासकों को इस संग्रह में अन्य संग्रह से आइटम मैप करने की अनुमति देता है। आप अन्य संग्रहों से आइटम खोज सकते हैं और उन्हें मैप कर सकते हैं, या वर्तमान में मैप किए गए आइटम की सूची ब्राउज़ कर सकते हैं।" + }, + "collection.edit.item-mapper.head": { + "message": "आइटम मैपर - अन्य संग्रहों से आइटम मैप करें" + }, + "collection.edit.item-mapper.no-search": { + "message": "कृपया खोजने के लिए एक प्रश्न दर्ज करें" + }, + "collection.edit.item-mapper.notifications.map.error.content": { + "message": "{{amount}} आइटम की मैपिंग में त्रुटियां हुईं।" + }, + "collection.edit.item-mapper.notifications.map.error.head": { + "message": "संलग्न करने में त्रुटियां" + }, + "collection.edit.item-mapper.notifications.map.success.content": { + "message": "{{amount}} आइटम सफलतापूर्वक मैप किए गए।" + }, + "collection.edit.item-mapper.notifications.map.success.head": { + "message": "मैपिंग पूरी हुई" + }, + "collection.edit.item-mapper.notifications.unmap.error.content": { + "message": "{{amount}} आइटम की मैपिंग निकालने में त्रुटियां हुईं।" + }, + "collection.edit.item-mapper.notifications.unmap.error.head": { + "message": "मैपिंग त्रुटियां हटाएं" + }, + "collection.edit.item-mapper.notifications.unmap.success.content": { + "message": "{{amount}} आइटम की मैपिंग सफलतापूर्वक निकाल दी गई।" + }, + "collection.edit.item-mapper.notifications.unmap.success.head": { + "message": "मैपिंग हटाना पूर्ण हुआ" + }, + "collection.edit.item-mapper.remove": { + "message": "चयनित आइटम मैपिंग हटाएं" + }, + "collection.edit.item-mapper.search-form.placeholder": { + "message": "आइटम खोजें..." + }, + "collection.edit.item-mapper.tabs.browse": { + "message": "मैप किए गए आइटम ब्राउज़ करें" + }, + "collection.edit.item-mapper.tabs.map": { + "message": "नए आइटम मैप करें" + }, + "collection.edit.item.authorizations.load-bundle-button": { + "message": "और बंडल लोड करें" + }, + "collection.edit.item.authorizations.load-more-button": { + "message": "और लोड करें" + }, + "collection.edit.item.authorizations.show-bitstreams-button": { + "message": "बंडल के लिए बिटस्ट्रीम नीतियां दिखाएं" + }, + "collection.edit.logo.delete-undo.title": { + "message": "हटाना रद्द करें " + }, + "collection.edit.logo.delete.title": { + "message": "चिन्ह हटाएं" + }, + "collection.edit.logo.label": { + "message": "संग्रह चिन्ह" + }, + "collection.edit.logo.notifications.add.error": { + "message": "संग्रह लोगो अपलोड करना विफल रहा। कृपया पुनः प्रयास करने से पहले सामग्री को सत्यापित करें।" + }, + "collection.edit.logo.notifications.add.success": { + "message": "संग्रह चिन्ह को सफलतापूर्वक अपलोड हुआ। " + }, + "collection.edit.logo.notifications.delete.error.title": { + "message": "चिन्ह हटाने में त्रुटि" + }, + "collection.edit.logo.notifications.delete.success.content": { + "message": "संग्रह चिन्ह सफलतापूर्वक हटा दिया गया" + }, + "collection.edit.logo.notifications.delete.success.title": { + "message": "चिन्ह हटा दिया गया" + }, + "collection.edit.logo.upload": { + "message": "अपलोड करने के लिए संग्रह लोगो छोड़ें" + }, + "collection.edit.notifications.success": { + "message": "संग्रह को सफलतापूर्वक संपादित किया गया" + }, + "collection.edit.return": { + "message": "वापस" + }, + "collection.edit.tabs.authorizations.head": { + "message": "प्राधिकरण" + }, + "collection.edit.tabs.authorizations.title": { + "message": "संग्रह संपादन - प्राधिकरण" + }, + "collection.edit.tabs.curate.head": { + "message": "क्यूरेट" + }, + "collection.edit.tabs.curate.title": { + "message": "संग्रह संपादन - क्यूरेट" + }, + "collection.edit.tabs.item-mapper.title": { + "message": "संग्रह संपादन - आइटम मैपर" + }, + "collection.edit.tabs.mapper.head": { + "message": "आइटम मैपर" + }, + "collection.edit.tabs.metadata.head": { + "message": "मेटाडेटा संपादित करें" + }, + "collection.edit.tabs.metadata.title": { + "message": "संग्रह संपादन के लिए मेटाडेटा" + }, + "collection.edit.tabs.roles.head": { + "message": "भूमिकाएँ निर्दिष्ट करें" + }, + "collection.edit.tabs.roles.title": { + "message": "संग्रह संपादन - भूमिकाएं" + }, + "collection.edit.tabs.source.external": { + "message": "यह संग्रह अपनी सामग्री को बाहरी स्रोत से एकत्रित करता है" + }, + "collection.edit.tabs.source.form.errors.oaiSource.required": { + "message": "आपको लक्ष्य संग्रह की एक निर्धारित आईडी प्रदान करनी होगी।" + }, + "collection.edit.tabs.source.form.harvestType": { + "message": "सामग्री हार्वेस्ट की जा रही है " + }, + "collection.edit.tabs.source.form.head": { + "message": "बाहरी स्रोत कॉन्फ़िगर करें" + }, + "collection.edit.tabs.source.form.metadataConfigId": { + "message": "मेटाडेटा प्रारूप" + }, + "collection.edit.tabs.source.form.oaiSetId": { + "message": "OAI specific set id" + }, + "collection.edit.tabs.source.form.oaiSource": { + "message": "OAI प्रदाता" + }, + "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_BITSTREAMS": { + "message": "हार्वेस्ट मेटाडेटा और बिटस्ट्रीम (ORE समर्थन की आवश्यकता है)" + }, + "collection.edit.tabs.source.form.options.harvestType.METADATA_AND_REF": { + "message": "हार्वेस्ट मेटाडेटा और बिटस्ट्रीम के संदर्भ (ORE समर्थन की आवश्यकता है)" + }, + "collection.edit.tabs.source.form.options.harvestType.METADATA_ONLY": { + "message": "केवल मेटाडेटा प्राप्त करें" + }, + "collection.edit.tabs.source.head": { + "message": "सामग्री स्रोत" + }, + "collection.edit.tabs.source.notifications.discarded.content": { + "message": "आपके परिवर्तन खारिज कर दिए गए थे। अपने परिवर्तनों को बहाल करने के लिए 'पूर्ववत करें' बटन पर क्लिक करें" + }, + "collection.edit.tabs.source.notifications.discarded.title": { + "message": "परिवर्तन रद्द किये गए" + }, + "collection.edit.tabs.source.notifications.invalid.content": { + "message": "आपके परिवर्तन सहेजे नहीं गए थे। कृपया सुनिश्चित करें कि आपके द्वारा सहेजने से पहले सभी फ़ील्ड मान्य हैं।" + }, + "collection.edit.tabs.source.notifications.invalid.title": { + "message": "अमान्य मेटाडेटा " + }, + "collection.edit.tabs.source.notifications.saved.content": { + "message": "इस संग्रह के सामग्री स्रोत में आपके परिवर्तन सहेजे गए थे।" + }, + "collection.edit.tabs.source.notifications.saved.title": { + "message": "सामग्री स्रोत सहेजा गया" + }, + "collection.edit.tabs.source.title": { + "message": "संग्रह संपादन के लिए सामग्री स्रोत" + }, + "collection.edit.template.add-button": { + "message": "जोड़ें" + }, + "collection.edit.template.breadcrumbs": { + "message": "टेम्पलेट आइटम" + }, + "collection.edit.template.cancel": { + "message": "रद्द करें" + }, + "collection.edit.template.delete-button": { + "message": "हटाएं" + }, + "collection.edit.template.edit-button": { + "message": "संपादित करें" + }, + "collection.edit.template.error": { + "message": "टेम्पलेट आइटम प्राप्त करने में त्रुटि हुई" + }, + "collection.edit.template.head": { + "message": "संग्रह के लिए टेम्पलेट आइटम संपादित करें \"{{ collection }}\"" + }, + "collection.edit.template.label": { + "message": "टेम्पलेट आइटम" + }, + "collection.edit.template.loading": { + "message": "टेम्प्लेट आइटम लोड हो रहा है..." + }, + "collection.edit.template.notifications.delete.error": { + "message": "आइटम टेम्पलेट हटाने में विफल" + }, + "collection.edit.template.notifications.delete.success": { + "message": "आइटम टेम्प्लेट को सफलतापूर्वक हटाया गया" + }, + "collection.edit.template.title": { + "message": "आइटम संपादन टेम्पलेट" + }, + "collection.form.abstract": { + "message": "संक्षिप्त वर्णन" + }, + "collection.form.description": { + "message": "परिचयात्मक पाठ (एचटीएमएल)" + }, + "collection.form.entityType": { + "message": "इकाई प्रकार" + }, + "collection.form.errors.title.required": { + "message": "कृपया संग्रह का नाम दर्ज करें " + }, + "collection.form.license": { + "message": "अनुज्ञाप‍त्र" + }, + "collection.form.provenance": { + "message": "उत्पत्ति" + }, + "collection.form.rights": { + "message": "कॉपीराइट टेक्स्ट (एचटीएमएल)" + }, + "collection.form.tableofcontents": { + "message": "समाचार (एचटीएमएल)" + }, + "collection.form.title": { + "message": "नाम" + }, + "collection.listelement.badge": { + "message": "संग्रह" + }, + "collection.page.browse.recent.empty": { + "message": "दिखाने के लिए कोई आइटम नहीं" + }, + "collection.page.browse.recent.head": { + "message": "हाल की प्रस्तुतियाँ" + }, + "collection.page.edit": { + "message": "इस संग्रह को संपादित करें" + }, + "collection.page.handle": { + "message": "इस संग्रह के लिए स्थायी यूआरआई (URI)" + }, + "collection.page.license": { + "message": "अनुज्ञाप‍त्र" + }, + "collection.page.license (Copy)": { + "message": "अनुज्ञाप‍त्र" + }, + "collection.page.news": { + "message": "समाचार" + }, + "collection.select.confirm": { + "message": "चयनित होने की पुष्टि करें" + }, + "collection.select.empty": { + "message": "दिखाने के लिए कोई संग्रह नहीं है" + }, + "collection.select.table.title": { + "message": "शीर्षक" + }, + "collection.source.controls.harvest.last": { + "message": "पिछला हार्वेस्ट:" + }, + "collection.source.controls.harvest.message": { + "message": "Harvest info:" + }, + "collection.source.controls.harvest.no-information": { + "message": "लागू नहीं" + }, + "collection.source.controls.harvest.start": { + "message": "हार्वेस्ट शुरू होने का समय:" + }, + "collection.source.controls.harvest.status": { + "message": "हार्वेस्ट स्थिति:" + }, + "collection.source.controls.head": { + "message": "हार्वेस्ट नियंत्रण" + }, + "collection.source.controls.import.completed": { + "message": "आयात पूरा हुआ" + }, + "collection.source.controls.import.failed": { + "message": "आयात के दौरान एक त्रुटि हुई" + }, + "collection.source.controls.import.running": { + "message": "आयात किया जा रहा है..." + }, + "collection.source.controls.import.submit": { + "message": "अभी आयात करें" + }, + "collection.source.controls.import.submit.error": { + "message": "आयात शुरू करने में कुछ गलत हुआ" + }, + "collection.source.controls.import.submit.success": { + "message": "आयात सफलतापूर्वक शुरू कर दिया गया है" + }, + "collection.source.controls.reset.completed": { + "message": "रीसेट और पुनः आयात पूरा हुआ" + }, + "collection.source.controls.reset.failed": { + "message": "रीसेट और पुन: आयात के दौरान एक त्रुटि हुई" + }, + "collection.source.controls.reset.running": { + "message": "रीसेट किया जा रहा है और फिर से आयात किया जा रहा है..." + }, + "collection.source.controls.reset.submit": { + "message": "रीसेट करें और पुनः आयात करें" + }, + "collection.source.controls.reset.submit.error": { + "message": "रीसेट शुरू करने और पुन: आयात करने में कुछ गलत हुआ" + }, + "collection.source.controls.reset.submit.success": { + "message": "रीसेट और पुनः आयात सफलतापूर्वक शुरू किया गया है" + }, + "collection.source.controls.test.completed": { + "message": "सेटिंग्स का परीक्षण करने के लिए स्क्रिप्ट सफलतापूर्वक समाप्त हो गई है" + }, + "collection.source.controls.test.failed": { + "message": "सेटिंग्स का परीक्षण करने की स्क्रिप्ट विफल हो गई है" + }, + "collection.source.controls.test.running": { + "message": "Testing configuration..." + }, + "collection.source.controls.test.submit": { + "message": "परीक्षण विन्यास" + }, + "collection.source.controls.test.submit.error": { + "message": "सेटिंग्स का परीक्षण शुरू करने में कुछ गलत हुआ" + }, + "collection.source.update.notifications.error.content": { + "message": "प्रदान की गई सेटिंग्स का परीक्षण किया गया है और काम नहीं किया है।" + }, + "collection.source.update.notifications.error.title": { + "message": "सर्वर त्रुटि" + }, + "comcol-role.edit.bitstream_read.anonymous-group": { + "message": "आने वाली बिटस्ट्रीम के लिए डिफ़ॉल्ट पठन वर्तमान में बेनामी पर सेट है।" + }, + "comcol-role.edit.bitstream_read.description": { + "message": "सामुदायिक प्रशासक उप-समुदाय या संग्रह बना सकते हैं, और उन उप-समुदायों या संग्रहों के लिए प्रबंधन या प्रबंधन सौंप सकते हैं। इसके अलावा, वे तय करते हैं कि कौन किसी भी उप-संग्रह में आइटम प्रस्तुत कर सकता है, आइटम मेटाडेटा (प्रस्तुति के बाद) संपादित कर सकता है, और अन्य संग्रहों (प्राधिकरण के अधीन) से मौजूदा आइटम जोड़ सकता है (मैप)।" + }, + "comcol-role.edit.bitstream_read.name": { + "message": "डिफ़ॉल्ट बिटस्ट्रीम पठन पहुंच" + }, + "comcol-role.edit.collection-admin.description": { + "message": "संग्रह व्यवस्थापक यह तय करते हैं कि संग्रह में आइटम कौन प्रस्तुत कर सकता है, आइटम मेटाडेटा संपादित कर सकता है (प्रस्तुति के बाद), और अन्य संग्रह से मौजूदा आइटम को इस संग्रह में जोड़ सकता है (उस संग्रह के लिए प्राधिकरण के अधीन)।" + }, + "comcol-role.edit.collection-admin.name": { + "message": "व्यवस्थापक" + }, + "comcol-role.edit.community-admin.description": { + "message": "सामुदायिक प्रशासक उप-समुदाय या संग्रह बना सकते हैं, और उन उप-समुदायों या संग्रहों के लिए प्रबंधन या प्रबंधन नियुक्त कर सकते हैं। इसके अलावा, वे तय करते हैं कि कौन किसी भी उप-संग्रह में आइटम प्रस्तुत कर सकता है, आइटम मेटाडेटा (सबमिशन के बाद) संपादित कर सकता है, और अन्य संग्रहों (प्राधिकरण के अधीन) से मौजूदा आइटम जोड़ सकता है (मैप)।" + }, + "comcol-role.edit.community-admin.name": { + "message": "व्यवस्थापक" + }, + "comcol-role.edit.create": { + "message": "बनाएं" + }, + "comcol-role.edit.create.error.title": { + "message": "'{{ role }}' भूमिका के लिए समूह बनाने में विफल" + }, + "comcol-role.edit.delete": { + "message": "हटाएं" + }, + "comcol-role.edit.delete.error.title": { + "message": "'{{ role }}' भूमिका के समूह को हटाने में विफल" + }, + "comcol-role.edit.editor.description": { + "message": "संपादक आने वाले प्रस्तुतियों के मेटाडेटा को संपादित करने में सक्षम हैं, और फिर उन्हें स्वीकार या अस्वीकार कर सकते हैं।" + }, + "comcol-role.edit.editor.name": { + "message": "संपादक" + }, + "comcol-role.edit.finaleditor.description": { + "message": "अंतिम संपादक आने वाले प्रस्तुति के मेटाडेटा को संपादित करने में सक्षम हैं, लेकिन उन्हें अस्वीकार नहीं कर पाएंगे।" + }, + "comcol-role.edit.finaleditor.name": { + "message": "अंतिम संपादक" + }, + "comcol-role.edit.item_read.anonymous-group": { + "message": "आने वाली वस्तुओं के लिए मानक पठन वर्तमान में बेनामी पर सेट है।" + }, + "comcol-role.edit.item_read.description": { + "message": "ई-लोग और समूह जो इस संग्रह में प्रस्तुत किए गए नए आइटम पढ़ सकते हैं। इस भूमिका में परिवर्तन पूर्वव्यापी नहीं हैं। सिस्टम में मौजूदा आइटम अभी भी उन लोगों द्वारा देखे जा सकेंगे जिनके पास जोड़ने के समय पढ़ने की पहुंच थी।" + }, + "comcol-role.edit.item_read.name": { + "message": "डिफ़ॉल्ट आइटम पढ़ने की अनुमति" + }, + "comcol-role.edit.no-group": { + "message": "कोई भी नहीं" + }, + "comcol-role.edit.restrict": { + "message": "प्रतिबंधित करें" + }, + "comcol-role.edit.reviewer.description": { + "message": "समीक्षक आने वाली प्रस्तुतियाँ स्वीकार या अस्वीकार करने में सक्षम हैं। हालांकि, वे प्रस्तुति के मेटाडेटा को संपादित करने में सक्षम नहीं हैं।" + }, + "comcol-role.edit.reviewer.name": { + "message": "समीक्षक" + }, + "comcol-role.edit.submitters.description": { + "message": "ई-व्यक्ति और समूह जिनके पास इस संग्रह में नए आइटम जमा करने की अनुमति है।" + }, + "comcol-role.edit.submitters.name": { + "message": "प्रस्तुतकर्ता" + }, + "community.all-lists.head": { + "message": "उपसमुदाय और संग्रह" + }, + "community.create.head": { + "message": "समुदाय बनाएं" + }, + "community.create.notifications.success": { + "message": "समुदाय सफलतापूर्वक बनाया गया" + }, + "community.create.sub-head": { + "message": "{{parent }} समुदाय के लिए एक उप-समुदाय बनाएं" + }, + "community.curate.header": { + "message": "क्यूरेट समुदाय: {{community}}" + }, + "community.delete.cancel": { + "message": "रद्द करें" + }, + "community.delete.confirm": { + "message": "पुष्टि करें" + }, + "community.delete.head": { + "message": "समुदाय हटाएं" + }, + "community.delete.notification.fail": { + "message": "समुदाय हटाया नहीं जा सका" + }, + "community.delete.notification.success": { + "message": "समुदाय को सफलतापूर्वक हटाया गया" + }, + "community.delete.processing": { + "message": "हटाया जा रहा है..." + }, + "community.delete.text": { + "message": "क्या आप वाकई \"{{dso }}\" समुदाय को हटाना चाहते हैं?" + }, + "community.edit.breadcrumbs": { + "message": "समुदाय संपादित करें" + }, + "community.edit.delete": { + "message": "इस समुदाय को हटाएं" + }, + "community.edit.head": { + "message": "समुदाय संपादित करें" + }, + "community.edit.logo.delete-undo.title": { + "message": "हटाना पूर्ववत करें" + }, + "community.edit.logo.delete.title": { + "message": "चिन्ह हटाएं" + }, + "community.edit.logo.label": { + "message": "समुदाय चिन्ह" + }, + "community.edit.logo.notifications.add.error": { + "message": "समुदाय का लोगो अपलोड करना विफल रहा। कृपया पुनः प्रयास करने से पहले सामग्री को सत्यापित करें।" + }, + "community.edit.logo.notifications.add.success": { + "message": "समुदाय का चिन्ह अपलोड करना सफल रहा|" + }, + "community.edit.logo.notifications.delete.error.title": { + "message": "चिन्ह हटाने में त्रुटि" + }, + "community.edit.logo.notifications.delete.success.content": { + "message": "समुदाय का चिन्ह सफलतापूर्वक हटा दिया गया" + }, + "community.edit.logo.notifications.delete.success.title": { + "message": "चिन्ह हटा दिया गया" + }, + "community.edit.logo.upload": { + "message": "अपलोड करने के लिए समुदाय का चिन्ह छोड़ें" + }, + "community.edit.notifications.error": { + "message": "समुदाय संपादित करते समय एक त्रुटि हुई" + }, + "community.edit.notifications.success": { + "message": "समुदाय को सफलतापूर्वक संपादित किया गया" + }, + "community.edit.notifications.unauthorized": { + "message": "आपके पास यह परिवर्तन करने के विशेषाधिकार नहीं हैं" + }, + "community.edit.return": { + "message": "वापस" + }, + "community.edit.tabs.authorizations.head": { + "message": "अनुज्ञा" + }, + "community.edit.tabs.authorizations.title": { + "message": "समुदाय संपादन - प्राधिकरण" + }, + "community.edit.tabs.curate.head": { + "message": "क्यूरेट" + }, + "community.edit.tabs.curate.title": { + "message": "समुदाय संपादन - क्यूरेट " + }, + "community.edit.tabs.metadata.head": { + "message": "मेटाडेटा संपादित करें" + }, + "community.edit.tabs.metadata.title": { + "message": "समुदाय संपादन - मेटाडेटा" + }, + "community.edit.tabs.roles.head": { + "message": "भूमिकाएँ निर्दिष्ट करें" + }, + "community.edit.tabs.roles.title": { + "message": "समुदाय संपादन - भूमिकाएँ " + }, + "community.form.abstract": { + "message": "संक्षिप्त वर्णन" + }, + "community.form.description": { + "message": "परिचयात्मक पाठ (एचटीएमएल)" + }, + "community.form.errors.title.required": { + "message": "कृपया समुदाय का नाम दर्ज करें" + }, + "community.form.rights": { + "message": "कॉपीराइट टेक्स्ट (एचटीएमएल)" + }, + "community.form.tableofcontents": { + "message": "समाचार (एचटीएमएल)" + }, + "community.form.title": { + "message": "नाम" + }, + "community.listelement.badge": { + "message": "समुदाय" + }, + "community.page.edit": { + "message": "इस समुदाय को संपादित करें" + }, + "community.page.handle": { + "message": "इस समुदाय के लिए स्थायी यूआरआई (URI)" + }, + "community.page.license": { + "message": "अनुज्ञाप‍त्र" + }, + "community.page.news": { + "message": "समाचार" + }, + "community.sub-collection-list.head": { + "message": "इस समुदाय के संग्रह" + }, + "community.sub-community-list.head": { + "message": "इस समुदाय के समुदाय" + }, + "communityList.breadcrumbs": { + "message": "समुदाय सूची" + }, + "communityList.showMore": { + "message": "और दिखाएं" + }, + "communityList.tabTitle": { + "message": "समुदाय सूची" + }, + "communityList.title": { + "message": "समुदायों की सूची" + }, + "confirmation-modal.delete-eperson.cancel": { + "message": "रद्द करें" + }, + "confirmation-modal.delete-eperson.confirm": { + "message": "हटाएं" + }, + "confirmation-modal.delete-eperson.header": { + "message": "\"{{ dsoName }}\" ई-व्यक्ति हटाएं" + }, + "confirmation-modal.delete-eperson.info": { + "message": "क्या आप वाकई ई-व्यक्ति \"{{dsoName}}\" को हटाना चाहते हैं" + }, + "confirmation-modal.delete-profile.cancel": { + "message": "रद्द करें" + }, + "confirmation-modal.delete-profile.confirm": { + "message": "हटाएं" + }, + "confirmation-modal.delete-profile.header": { + "message": "प्रोफ़ाइल हटाएं" + }, + "confirmation-modal.delete-profile.info": { + "message": "क्या आप वाकई अपनी प्रोफ़ाइल हटाना चाहते हैं" + }, + "confirmation-modal.export-metadata.cancel": { + "message": "रद्द करें" + }, + "confirmation-modal.export-metadata.confirm": { + "message": "निर्यात करें" + }, + "confirmation-modal.export-metadata.header": { + "message": "{{ dsoName }} के लिए मेटाडेटा निर्यात करें" + }, + "confirmation-modal.export-metadata.info": { + "message": "क्या आप वाकई {{ dsoName }} के लिए मेटाडेटा निर्यात करना चाहते हैं" + }, + "cookies.consent.accept-all": { + "message": "सभी स्वीकार करें" + }, + "cookies.consent.accept-selected": { + "message": "चयनित को स्वीकार करें" + }, + "cookies.consent.app.description.acknowledgement": { + "message": "आपकी पावती और सहमति को सहेजने के लिए आवश्यक" + }, + "cookies.consent.app.description.authentication": { + "message": "आपको साइन इन करने के लिए आवश्यक" + }, + "cookies.consent.app.description.google-analytics": { + "message": "हमें सांख्यिकीय जानकारी पर नज़र रखने की अनुमति देता है" + }, + "cookies.consent.app.description.preferences": { + "message": "आपकी प्राथमिकताएं सहेजने के लिए आवश्यक" + }, + "cookies.consent.app.opt-out.description": { + "message": "यह ऐप डिफ़ॉल्ट रूप से लोड होता है (लेकिन आप ऑप्ट आउट कर सकते हैं)" + }, + "cookies.consent.app.opt-out.title": { + "message": "(बाहर निकलें)" + }, + "cookies.consent.app.purpose": { + "message": "उद्देश्य" + }, + "cookies.consent.app.required.description": { + "message": "यह एप्लिकेशन हमेशा आवश्यक है" + }, + "cookies.consent.app.required.title": { + "message": "(हमेशा आवश्यक)" + }, + "cookies.consent.app.title.acknowledgement": { + "message": "स्वीकृति" + }, + "cookies.consent.app.title.authentication": { + "message": "प्रमाणीकरण" + }, + "cookies.consent.app.title.google-analytics": { + "message": "गूगल एनालिटिक्स" + }, + "cookies.consent.app.title.preferences": { + "message": "प्राथमिकताएं" + }, + "cookies.consent.close": { + "message": "बंद करें" + }, + "cookies.consent.content-modal.description": { + "message": "यहां आप हमारे द्वारा आपके बारे में एकत्रित की गई जानकारी को देख और अनुकूलित कर सकते हैं।" + }, + "cookies.consent.content-modal.privacy-policy.name": { + "message": "गोपनीयता नीति" + }, + "cookies.consent.content-modal.privacy-policy.text": { + "message": "अधिक जानने के लिए, हमारी {privacyPolicy} पढ़ें।" + }, + "cookies.consent.content-modal.title": { + "message": "जानकारी जो हम एकत्र करते हैं" + }, + "cookies.consent.content-notice.description": { + "message": "हम निम्नलिखित उद्देश्यों के लिए आपकी व्यक्तिगत जानकारी एकत्र और संसाधित करते हैं: प्रमाणीकरण, प्राथमिकताएं, पावती और सांख्यिकी
अधिक जानने के लिए, कृपया हमारी {privacyPolicy} पढ़ें।" + }, + "cookies.consent.content-notice.description.no-privacy": { + "message": "हम निम्नलिखित उद्देश्यों के लिए आपकी व्यक्तिगत जानकारी एकत्र और संसाधित करते हैं: प्रमाणीकरण, प्राथमिकताएं, पावती और सांख्यिकी।" + }, + "cookies.consent.content-notice.learnMore": { + "message": "अनुकूलित करें" + }, + "cookies.consent.decline": { + "message": "अस्वीकार" + }, + "cookies.consent.purpose.functional": { + "message": "कार्यात्मक" + }, + "cookies.consent.purpose.statistical": { + "message": "सांख्यिकीय" + }, + "cookies.consent.update": { + "message": "आपकी पिछली विज़िट के बाद से परिवर्तन हुए हैं, कृपया अपनी सहमति अपडेट करें।" + }, + "curation-task.task.checklinks.label": { + "message": "मेटाडेटा में लिंक जांचें" + }, + "curation-task.task.noop.label": { + "message": "NOOP" + }, + "curation-task.task.profileformats.label": { + "message": "प्रोफ़ाइल बिटस्ट्रीम प्रारूप" + }, + "curation-task.task.requiredmetadata.label": { + "message": "आवश्यक मेटाडेटा की जाँच करें" + }, + "curation-task.task.translate.label": { + "message": "माइक्रोसॉफ्ट अनुवादक" + }, + "curation-task.task.vscan.label": { + "message": "वायरस जाँच" + }, + "curation.form.handle.hint": { + "message": "संकेत: पूरी साइट पर कार्य चलाने के लिए [your-handle-prefix]/0 दर्ज करें (सभी कार्य इस क्षमता का समर्थन नहीं करते हैं)" + }, + "curation.form.handle.label": { + "message": "हैंडल:" + }, + "curation.form.submit": { + "message": "शुरू करें" + }, + "curation.form.submit.error.content": { + "message": "क्यूरेशन कार्य प्रारंभ करने का प्रयास करते समय कोई त्रुटि उत्पन्न हुई।" + }, + "curation.form.submit.error.head": { + "message": "क्यूरेशन टास्क चलाना विफल रहा" + }, + "curation.form.submit.error.invalid-handle": { + "message": "इस ऑब्जेक्ट के लिए हैंडल निर्धारित नहीं किया जा सका" + }, + "curation.form.submit.success.content": { + "message": "आपको संबंधित प्रक्रिया पृष्ठ पर पुनः निर्देशित किया जाएगा।" + }, + "curation.form.submit.success.head": { + "message": "क्यूरेशन कार्य सफलतापूर्वक शुरू किया गया है" + }, + "curation.form.task-select.label": { + "message": "कार्य:" + }, + "default-relationships.search.results.head": { + "message": "खोज के परिणाम" + }, + "default.search.results.head": { + "message": "खोज के परिणाम" + }, + "deny-request-copy.email.message": { + "message": "प्रिय {{ recipientName }},\nआपके अनुरोध के प्रत्युत्तर में मुझे आपको यह बताते हुए खेद हो रहा है कि आपके द्वारा अनुरोधित फ़ाइल (फ़ाइलों) की एक प्रति, दस्तावेज़ के संबंध में भेजना संभव नहीं है: \"{{itemUrl }}\" ({{itemName }}), जिनमें से मैं एक लेखक हूँ।\n\nसाभार,\n{{ authorName }} <{{ authorEmail }}>" + }, + "deny-request-copy.email.subject": { + "message": "दस्तावेज़ की प्रति का अनुरोध करें" + }, + "deny-request-copy.error": { + "message": "त्रुटि पाई गई" + }, + "deny-request-copy.header": { + "message": "दस्तावेज़ की प्रतिलिपि अनुरोध अस्वीकार करें" + }, + "deny-request-copy.intro": { + "message": "यह संदेश अनुरोध के आवेदक को भेजा जाएगा" + }, + "deny-request-copy.success": { + "message": "आइटम अनुरोध को सफलतापूर्वक अस्वीकार कर दिया गया" + }, + "dso-selector.claim.item.body": { + "message": "ये मौजूदा प्रोफ़ाइल हैं जो आपसे संबंधित हो सकती हैं। यदि आप इनमें से किसी एक प्रोफाइल में खुद को पहचानते हैं, तो इसे चुनें और विवरण पृष्ठ पर, विकल्पों में से, इसका दावा करना चुनें। अन्यथा आप नीचे दिए गए बटन का उपयोग करके नए सिरे से एक नई प्रोफ़ाइल बना सकते हैं।" + }, + "dso-selector.claim.item.create-from-scratch": { + "message": "नया बनाएँ" + }, + "dso-selector.claim.item.head": { + "message": "प्रोफाइल टिप्स" + }, + "dso-selector.claim.item.not-mine-label": { + "message": "इनमें से कोई भी मेरा नहीं है" + }, + "dso-selector.create.collection.head": { + "message": "नया संग्रह" + }, + "dso-selector.create.collection.sub-level": { + "message": "में नया संग्रह बनाएं" + }, + "dso-selector.create.community.head": { + "message": "नया समुदाय" + }, + "dso-selector.create.community.sub-level": { + "message": "में नया समुदाय बनाएं" + }, + "dso-selector.create.community.top-level": { + "message": "नया शीर्ष-स्तरीय समुदाय बनाएं" + }, + "dso-selector.create.item.head": { + "message": "नया आइटम" + }, + "dso-selector.create.item.sub-level": { + "message": "में नया आइटम बनाएं" + }, + "dso-selector.create.submission.head": { + "message": "नवीन प्रस्तुतीकरण" + }, + "dso-selector.edit.collection.head": { + "message": "संग्रह संपादित करें" + }, + "dso-selector.edit.community.head": { + "message": "समुदाय संपादित करें" + }, + "dso-selector.edit.item.head": { + "message": "आइटम संपादित करें" + }, + "dso-selector.error.title": { + "message": "{{type }} खोजने में त्रुटि हुई" + }, + "dso-selector.export-metadata.dspaceobject.head": { + "message": "से मेटाडेटा निर्यात करें" + }, + "dso-selector.no-results": { + "message": "{{ type }} नहीं मिला" + }, + "dso-selector.placeholder": { + "message": "{{ type }} खोजें" + }, + "dso-selector.select.collection.head": { + "message": "संग्रह का चयन करें" + }, + "dso-selector.set-scope.community.button": { + "message": "संपूर्ण डीस्पेस में खोजें " + }, + "dso-selector.set-scope.community.head": { + "message": "खोज का दायरा चुनें" + }, + "dso-selector.set-scope.community.input-header": { + "message": "समुदाय या संग्रह के लिए खोजें" + }, + "dso.name.untitled": { + "message": "शीर्षकहीन" + }, + "error-page.description.401": { + "message": "अनधिकृत" + }, + "error-page.description.403": { + "message": "अनधिकृत" + }, + "error-page.description.404": { + "message": "पृष्ठ नहीं मिला" + }, + "error-page.description.500": { + "message": "सेवा उप्लब्ध् नहीं है" + }, + "error-page.orcid.generic-error": { + "message": "ORCID के माध्यम से लॉगिन के दौरान एक त्रुटि हुई। सुनिश्चित करें कि आपने अपना ORCID खाता ईमेल पता डीस्पेस के साथ साझा किया है। यदि त्रुटि बनी रहती है, तो व्यवस्थापक से संपर्क करें" + }, + "error.bitstream": { + "message": "बिटस्ट्रीम लाने में त्रुटि" + }, + "error.browse-by": { + "message": "आइटम लाने में त्रुटि" + }, + "error.collection": { + "message": "संग्रह लाने में त्रुटि" + }, + "error.collections": { + "message": "संग्रह लाने में त्रुटि" + }, + "error.community": { + "message": "समुदाय लाने में त्रुटि" + }, + "error.default": { + "message": "त्रुटि" + }, + "error.identifier": { + "message": "पहचानकर्ता के लिए कोई आइटम नहीं मिला" + }, + "error.invalid-search-query": { + "message": "खोज क्वेरी मान्य नहीं है. कृपया इस त्रुटि के बारे में अधिक जानकारी के लिए Solr query syntax सर्वोत्तम अभ्यास देखें ." + }, + "error.item": { + "message": "आइटम लाने में त्रुटि" + }, + "error.items": { + "message": "आइटम लाने में त्रुटि" + }, + "error.objects": { + "message": "मदो को लाने में त्रुटि" + }, + "error.recent-submissions": { + "message": "हाल ही की प्रस्तुतियां लाने में त्रुटि" + }, + "error.search-results": { + "message": "खोज परिणाम लाने में त्रुटि" + }, + "error.sub-collections": { + "message": "उप-संग्रह लाने में त्रुटि" + }, + "error.sub-communities": { + "message": "उप-समुदाय लाने में त्रुटि" + }, + "error.submission.sections.init-form-error": { + "message": "अनुभाग आरंभीकरण के दौरान त्रुटि हुई, कृपया अपने निविष्ट-फॉर्म विन्यास की जाँच करें। विवरण नीचे हैं:

" + }, + "error.top-level-communities": { + "message": "शीर्ष-स्तरीय समुदायों को लाने में त्रुटि" + }, + "error.validation.emailTaken": { + "message": "यह ई - मेल पहले ही लिया जा चुका हैं" + }, + "error.validation.filerequired": { + "message": "फ़ाइल अपलोड अनिवार्य है" + }, + "error.validation.groupExists": { + "message": "यह समूह पहले से मौजूद है" + }, + "error.validation.license.notgranted": { + "message": "अपना प्रस्तुतीकरण पूरा करने के लिए आपको यह अनुज्ञापत्र देना होगा। यदि आप इस समय यह अनुज्ञापत्र देने में असमर्थ हैं तो आप अपना काम सहेज सकते हैं और बाद में वापस आ सकते हैं या प्रस्तुतीकरण हटा सकते हैं।" + }, + "error.validation.NotValidEmail": { + "message": "यह ई-मेल वैध ईमेल नहीं है" + }, + "error.validation.pattern": { + "message": "यह इनपुट वर्तमान ढांचे द्वारा प्रतिबंधित है: {{ pattern }}." + }, + "error.validation.required": { + "message": "यह फ़ील्ड आवश्यक है" + }, + "feed.description": { + "message": "सिंडिकेशन फ़ीड" + }, + "file-section.error.header": { + "message": "इस मद के लिए फ़ाइलें प्राप्त करने में त्रुटि" + }, + "footer.copyright": { + "message": "कॉपीराइट © 2002-{{ year }}" + }, + "footer.link.cookies": { + "message": "कुकी सेटिंग" + }, + "footer.link.dspace": { + "message": "डीस्पेस सॉफ्टवेयर" + }, + "footer.link.end-user-agreement": { + "message": "अंतिम उपयोगकर्ता समझौता" + }, + "footer.link.feedback": { + "message": "प्रतिक्रिया भेजें" + }, + "footer.link.lyrasis": { + "message": "लाइरासिस" + }, + "footer.link.privacy-policy": { + "message": "गोपनीयता नीति" + }, + "forgot-email.form.email": { + "message": "ईमेल पता *" + }, + "forgot-email.form.email.error.pattern": { + "message": "कृपया एक मान्य ईमेल पता भरें" + }, + "forgot-email.form.email.error.required": { + "message": "कृपया ईमेल पता भरें" + }, + "forgot-email.form.email.hint": { + "message": "आगे के निर्देशों के साथ इस पते पर एक ईमेल भेजा जाएगा।" + }, + "forgot-email.form.error.content": { + "message": "निम्नलिखित ईमेल पते से जुड़े खाते के लिए पासवर्ड रीसेट करने का प्रयास करते समय एक त्रुटि हुई: {{ email }}" + }, + "forgot-email.form.error.head": { + "message": "पासवर्ड रीसेट करने का प्रयास करते समय त्रुटि" + }, + "forgot-email.form.header": { + "message": "पासवर्ड भूल गए" + }, + "forgot-email.form.info": { + "message": "खाते से संबद्ध ईमेल पता दर्ज करें।" + }, + "forgot-email.form.submit": { + "message": "पासवर्ड रीसेट" + }, + "forgot-email.form.success.content": { + "message": "{{email}} को एक विशेष यूआरएल और अन्य निर्देशों के साथ एक ईमेल भेजा गया है।" + }, + "forgot-email.form.success.head": { + "message": "पासवर्ड रीसेट ईमेल भेजा गया" + }, + "forgot-password.form.card.security": { + "message": "सुरक्षा" + }, + "forgot-password.form.error.empty-password": { + "message": "कृपया नीचे दिए गए बॉक्स में पासवर्ड दर्ज करें।" + }, + "forgot-password.form.error.matching-passwords": { + "message": "पासवर्ड एक - दूसरे से मिलते - जुलते नहीं हैं।" + }, + "forgot-password.form.error.password-length": { + "message": "पासवर्ड कम से कम 6 अक्षर लंबा होना चाहिए।" + }, + "forgot-password.form.head": { + "message": "पासवर्ड भूल गए" + }, + "forgot-password.form.identification.email": { + "message": "ईमेल पता:" + }, + "forgot-password.form.identification.header": { + "message": "पहचान" + }, + "forgot-password.form.info": { + "message": "नीचे दिए गए बॉक्स में एक नया पासवर्ड दर्ज करें, और दूसरे बॉक्स में फिर से टाइप करके इसकी पुष्टि करें। यह कम से कम छह वर्ण लंबा होना चाहिए।" + }, + "forgot-password.form.label.password": { + "message": "पासवर्ड" + }, + "forgot-password.form.label.passwordrepeat": { + "message": "पुष्टि करने के लिए फिर से लिखें" + }, + "forgot-password.form.notification.error.title": { + "message": "नया पासवर्ड सबमिट करने का प्रयास करते समय त्रुटि" + }, + "forgot-password.form.notification.success.content": { + "message": "पासवर्ड रीसेट सफल रहा। आपको बनाए गए उपयोगकर्ता के रूप में लॉग इन किया गया है।" + }, + "forgot-password.form.notification.success.title": { + "message": "पासवर्ड रीसेट पूरा हुआ" + }, + "forgot-password.form.submit": { + "message": "पासवर्ड सबमिट करें" + }, + "forgot-password.title": { + "message": "पासवर्ड भूल गए" + }, + "form.add": { + "message": "और जोड़ें" + }, + "form.add-help": { + "message": "वर्तमान प्रविष्टि जोड़ने और दूसरी प्रविष्टि जोड़ने के लिए यहां क्लिक करें" + }, + "form.cancel": { + "message": "रद्द करें" + }, + "form.clear": { + "message": "साफ़ करें" + }, + "form.clear-help": { + "message": "चयनित मान को हटाने के लिए यहां क्लिक करें" + }, + "form.discard": { + "message": "खारिज करें" + }, + "form.drag": { + "message": "खींचें (Drag)" + }, + "form.edit": { + "message": "संपादित करें" + }, + "form.edit-help": { + "message": "चयनित मान संपादित करने के लिए यहां क्लिक करें" + }, + "form.first-name": { + "message": "प्रथम नाम" + }, + "form.group-collapse": { + "message": "संक्षिप्त करें" + }, + "form.group-collapse-help": { + "message": "संक्षिप्त करने के लिए यहां क्लिक करें" + }, + "form.group-expand": { + "message": "विस्तृत करें" + }, + "form.group-expand-help": { + "message": "विस्तार करने और अधिक तत्व जोड़ने के लिए यहां क्लिक करें" + }, + "form.last-name": { + "message": "उपनाम" + }, + "form.loading": { + "message": "लोड हो रहा है..." + }, + "form.lookup": { + "message": "देखो" + }, + "form.lookup-help": { + "message": "मौजूदा संबंध देखने के लिए यहां क्लिक करें" + }, + "form.no-results": { + "message": "कोई परिणाम नहीं मिला" + }, + "form.no-value": { + "message": "कोई मान दर्ज नहीं किया गया" + }, + "form.remove": { + "message": "हटाएं" + }, + "form.repeatable.sort.tip": { + "message": "आइटम को नई स्थिति में छोड़ें" + }, + "form.save": { + "message": "सहेजें" + }, + "form.save-help": { + "message": "परिवर्तन सहेजें" + }, + "form.search": { + "message": "खोजें" + }, + "form.search-help": { + "message": "मौजूदा पत्राचार देखने के लिए यहां क्लिक करें" + }, + "form.submit": { + "message": "सहेजें" + }, + "general.back": { + "message": "वापस" + }, + "general.cancel": { + "message": "रद्द करें" + }, + "general.confirm": { + "message": "क्या आपको यकीन है?" + }, + "general.destroy": { + "message": "हटाएं" + }, + "general.edit": { + "message": "संपादित करें" + }, + "general.new": { + "message": "नया" + }, + "grant-deny-request-copy.deny": { + "message": "कॉपी न भेजें" + }, + "grant-deny-request-copy.email.back": { + "message": "वापस" + }, + "grant-deny-request-copy.email.message": { + "message": "संदेश" + }, + "grant-deny-request-copy.email.message.empty": { + "message": "कृपया संदेश दर्ज करें" + }, + "grant-deny-request-copy.email.permissions.info": { + "message": "इन अनुरोधों का जवाब देने से बचने के लिए आप इस अवसर का उपयोग दस्तावेज़ पर पहुंच प्रतिबंधों पर पुनर्विचार करने के लिए कर सकते हैं। यदि आप रिपॉजिटरी व्यवस्थापकों से इन प्रतिबंधों को हटाने के लिए कहना चाहते हैं, तो कृपया नीचे दिए गए बॉक्स को चेक करें।" + }, + "grant-deny-request-copy.email.permissions.label": { + "message": "ओपन एक्सेस में बदलें" + }, + "grant-deny-request-copy.email.send": { + "message": "भेजें" + }, + "grant-deny-request-copy.email.subject": { + "message": "विषय" + }, + "grant-deny-request-copy.email.subject.empty": { + "message": "कृपया एक विषय दर्ज करें" + }, + "grant-deny-request-copy.grant": { + "message": "प्रतिलिपि भेजें" + }, + "grant-deny-request-copy.header": { + "message": "दस्तावेज़ की प्रतिलिपि अनुरोध" + }, + "grant-deny-request-copy.home-page": { + "message": "मुझे होम पेज पर ले जाएं" + }, + "grant-deny-request-copy.intro1": { + "message": "यदि आप {{ name }} दस्तावेज़ के लेखकों में से एक हैं, तो कृपया उपयोगकर्ता के अनुरोध का जवाब देने के लिए नीचे दिए गए विकल्पों में से किसी एक का उपयोग करें।" + }, + "grant-deny-request-copy.intro2": { + "message": "एक विकल्प चुनने के बाद, आपको एक सुझाया गया ईमेल उत्तर प्रस्तुत किया जाएगा जिसे आप संपादित कर सकते हैं।" + }, + "grant-deny-request-copy.processed": { + "message": "यह अनुरोध पहले ही संसाधित किया जा चुका है। होम पृष्ठ पर वापस जाने के लिए आप नीचे दिए गए बटन का उपयोग कर सकते हैं।" + }, + "grant-request-copy.email.message": { + "message": "प्रिय {{ recipientName }},\nआपके अनुरोध के प्रत्युत्तर में मुझे आपको \"{{ itemUrl }}\" ({{itemName }}) दस्तावेज़ से संबंधित फ़ाइल(ो),जिसका मैं एक लेखक हूं, की प्रति संलग्न करते हुए प्रसन्नता हो रही है।\n\nसाभार,\n{{ authorName }} <{{ authorEmail }}>" + }, + "grant-request-copy.email.subject": { + "message": "दस्तावेज़ की प्रति का अनुरोध करें" + }, + "grant-request-copy.error": { + "message": "एक त्रुटि हुई" + }, + "grant-request-copy.header": { + "message": "दस्तावेज़ कॉपी अनुरोध प्रदान करें" + }, + "grant-request-copy.intro": { + "message": "यह संदेश अनुरोध के आवेदक को भेजा जाएगा। अनुरोधित दस्तावेज संलग्न किए जाएंगे।" + }, + "grant-request-copy.success": { + "message": "आइटम अनुरोध सफलतापूर्वक स्वीकृत किया गया" + }, + "health-page.error.msg": { + "message": "स्वास्थ्य जांच सेवा अस्थायी रूप से अनुपलब्ध है" + }, + "health-page.heading": { + "message": "स्वास्थ्य" + }, + "health-page.info-tab": { + "message": "जानकारी" + }, + "health-page.property.status": { + "message": "स्थिति कोड" + }, + "health-page.section-info.app.title": { + "message": "सॉफ्टवेयर बैकएंड" + }, + "health-page.section-info.java.title": { + "message": "जावा" + }, + "health-page.section.db.title": { + "message": "डेटाबेस" + }, + "health-page.section.geoIp.title": { + "message": "जियोआईपी (GeoIp)" + }, + "health-page.section.no-issues": { + "message": "कोई समस्या नहीं मिली" + }, + "health-page.section.solrAuthorityCore.title": { + "message": "Sor: प्राधिकरण कोर" + }, + "health-page.section.solrOaiCore.title": { + "message": "Sor: oai कोर" + }, + "health-page.section.solrSearchCore.title": { + "message": "Sor: मूल खोज" + }, + "health-page.section.solrStatisticsCore.title": { + "message": "Sor: सांख्यिकी कोर" + }, + "health-page.status": { + "message": "स्थिति" + }, + "health-page.status-tab": { + "message": "स्थिति" + }, + "health-page.status.error.info": { + "message": "समस्याएं पाई गईं" + }, + "health-page.status.ok.info": { + "message": "परिचालन" + }, + "health-page.status.warning.info": { + "message": "संभावित समस्याओं का पता चला" + }, + "health-page.title": { + "message": "स्वास्थ्य" + }, + "health.breadcrumbs": { + "message": "स्वास्थ्य" + }, + "hello": { + "message": "नमस्ते" + }, + "home.breadcrumbs": { + "message": "मुख्य पृष्ठ" + }, + "home.description": { + "message": null + }, + "home.search-form.placeholder": { + "message": "संग्रहालय में खोजें..." + }, + "home.title": { + "message": "मुख्य पृष्ठ" + }, + "home.top-level-communities.head": { + "message": "डीस्पेस में समुदाय" + }, + "home.top-level-communities.help": { + "message": "किसी समुदाय के संग्रह ब्राउज़ करने के लिए उसे चुनें." + }, + "idle-modal.extend-session": { + "message": "सत्र बढ़ाएँ" + }, + "idle-modal.header": { + "message": "सत्र जल्द ही समाप्त होगा" + }, + "idle-modal.info": { + "message": "सुरक्षा कारणों से, उपयोगकर्ता सत्र {{timeToExpire}} मिनट की निष्क्रियता के बाद समाप्त हो जाते हैं। आपका सत्र जल्द ही समाप्त हो जाएगा। क्या आप इसे बढ़ाना चाहते हैं या लॉग आउट करना चाहते हैं?" + }, + "idle-modal.log-out": { + "message": "लॉग आउट" + }, + "iiif.listelement.badge": { + "message": "छवि मीडिया" + }, + "iiif.page.description": { + "message": "विवरण: " + }, + "iiif.page.doi": { + "message": "स्थायी लिंक: " + }, + "iiif.page.issue": { + "message": "अंक: " + }, + "iiif.page.titleprefix": { + "message": "छवि: " + }, + "iiifsearchable.listelement.badge": { + "message": "दस्तावेज़ मीडिया" + }, + "iiifsearchable.page.description": { + "message": "विवरण: " + }, + "iiifsearchable.page.doi": { + "message": "स्थायी लिंक:" + }, + "iiifsearchable.page.issue": { + "message": "अंक:" + }, + "iiifsearchable.page.titleprefix": { + "message": "दस्तावेज़: " + }, + "iiifviewer.fullscreen.notice": { + "message": "बेहतर देखने के लिए पूर्ण स्क्रीन का उपयोग करें।" + }, + "info.end-user-agreement.accept": { + "message": "मैंने पढ़ लिया है और मैं अंतिम उपयोगकर्ता अनुबंध से सहमत हूं" + }, + "info.end-user-agreement.accept.error": { + "message": "अंतिम उपयोगकर्ता अनुबंध को स्वीकार करते हुए एक त्रुटि उत्पन्न हुई" + }, + "info.end-user-agreement.accept.success": { + "message": "अंतिम उपयोगकर्ता अनुबंध को सफलतापूर्वक अपडेट किया गया" + }, + "info.end-user-agreement.breadcrumbs": { + "message": "अंतिम उपयोगकर्ता समझौता" + }, + "info.end-user-agreement.buttons.cancel": { + "message": "रद्द करें" + }, + "info.end-user-agreement.buttons.save": { + "message": "सहेजें" + }, + "info.end-user-agreement.head": { + "message": "अंतिम उपयोगकर्ता समझौता" + }, + "info.end-user-agreement.title": { + "message": "अंतिम उपयोगकर्ता समझौता" + }, + "info.feedback.breadcrumbs": { + "message": "प्रतिपुष्टि" + }, + "info.feedback.comments": { + "message": "टिप्पणियाँ" + }, + "info.feedback.create.success": { + "message": "फ़ीडबैक सफलतापूर्वक भेजा गया!" + }, + "info.feedback.email_help": { + "message": "इस पते का उपयोग आपकी प्रतिक्रिया पर अनुवर्ती कार्रवाई के लिए किया जाएगा।" + }, + "info.feedback.email-label": { + "message": "तुम्हारा ईमेल" + }, + "info.feedback.error.email.required": { + "message": "मान्य ईमेल पता जरूरी है" + }, + "info.feedback.error.message.required": { + "message": "एक टिप्पणी आवश्यक है" + }, + "info.feedback.head": { + "message": "प्रतिपुष्टि" + }, + "info.feedback.info": { + "message": "डीस्पेस सिस्टम के बारे में अपनी प्रतिक्रिया साझा करने के लिए धन्यवाद। आपकी टिप्पणियों की सराहना की जाती है!" + }, + "info.feedback.page_help": { + "message": "आपकी प्रतिक्रिया से संबंधित पेज" + }, + "info.feedback.page-label": { + "message": "पृष्ठ" + }, + "info.feedback.send": { + "message": "प्रतिक्रिया भेजें" + }, + "info.feedback.title": { + "message": "प्रतिपुष्टि" + }, + "info.privacy.breadcrumbs": { + "message": "गोपनीयता कथन" + }, + "info.privacy.head": { + "message": "गोपनीयता वाले कथन" + }, + "info.privacy.title": { + "message": "गोपनीयता कथन" + }, + "item.alerts.private": { + "message": "यह आइटम खोजने योग्य नहीं है" + }, + "item.alerts.withdrawn": { + "message": "इस मद को वापस ले लिया गया है" + }, + "item.badge.private": { + "message": "गैर-खोज योग्य" + }, + "item.badge.withdrawn": { + "message": "वापस लिया गया" + }, + "item.bitstreams.upload.bundle": { + "message": "बंडल" + }, + "item.bitstreams.upload.bundle.new": { + "message": "बंडल बनाएं" + }, + "item.bitstreams.upload.bundle.placeholder": { + "message": "एक बंडल का चयन करें अथवा नये बंडल नाम डालें" + }, + "item.bitstreams.upload.bundles.empty": { + "message": "इस आइटम में बिटस्ट्रीम अपलोड करने के लिए कोई बंडल नहीं है।" + }, + "item.bitstreams.upload.cancel": { + "message": "रद्द करें" + }, + "item.bitstreams.upload.drop-message": { + "message": "अपलोड करने के लिए एक फ़ाइल छोड़ें" + }, + "item.bitstreams.upload.item": { + "message": "आइटम: " + }, + "item.bitstreams.upload.notifications.bundle.created.content": { + "message": "नया बंडल सफलतापूर्वक बनाया गया।" + }, + "item.bitstreams.upload.notifications.bundle.created.title": { + "message": "बंडल बन गया" + }, + "item.bitstreams.upload.notifications.upload.failed": { + "message": "अपलोड विफल रहा। कृपया पुनः प्रयास करने से पहले सामग्री को सत्यापित करें।" + }, + "item.bitstreams.upload.title": { + "message": "बिटस्ट्रीम अपलोड करें" + }, + "item.edit.authorizations.heading": { + "message": "इस संपादक के साथ आप किसी आइटम की नीतियों को देख और बदल सकते हैं, साथ ही अलग-अलग आइटम घटकों (बंडल और बिटस्ट्रीम) की नीतियों को बदल सकते हैं। संक्षेप में, आइटम बंडलों का कंटेनर होता है, और बंडल बिटस्ट्रीम के कंटेनर होते हैं। कंटेनर में आमतौर पर जोड़ें/निकालें/पढ़ें/लिखें नीतियां होती हैं, जबकि बिटस्ट्रीम में केवल पढ़ने/लिखने की नीतियां होती हैं।" + }, + "item.edit.authorizations.title": { + "message": "आइटम की नीतियां संपादित करें" + }, + "item.edit.bitstreams.bundle.displaying": { + "message": "वर्तमान में {{ total }} की {{ amount }} बिटस्ट्रीम प्रदर्शित कर रहा है।" + }, + "item.edit.bitstreams.bundle.edit.buttons.upload": { + "message": "अपलोड" + }, + "item.edit.bitstreams.bundle.load.all": { + "message": "({{ total }}) सभी लोड करें" + }, + "item.edit.bitstreams.bundle.load.more": { + "message": "और लोड करें" + }, + "item.edit.bitstreams.bundle.name": { + "message": "बंडल: {{ name }}" + }, + "item.edit.bitstreams.discard-button": { + "message": "रद्द करें" + }, + "item.edit.bitstreams.edit.buttons.download": { + "message": "डाउनलोड" + }, + "item.edit.bitstreams.edit.buttons.drag": { + "message": "खींचें (Drag)" + }, + "item.edit.bitstreams.edit.buttons.edit": { + "message": "संपादित करें" + }, + "item.edit.bitstreams.edit.buttons.remove": { + "message": "हटाएं" + }, + "item.edit.bitstreams.edit.buttons.undo": { + "message": "परिवर्तन पूर्ववत करें" + }, + "item.edit.bitstreams.empty": { + "message": "इस आइटम में कोई बिटस्ट्रीम नहीं है। एक बनाने के लिए अपलोड बटन पर क्लिक करें।" + }, + "item.edit.bitstreams.headers.actions": { + "message": "गतिविधियां" + }, + "item.edit.bitstreams.headers.bundle": { + "message": "बंडल" + }, + "item.edit.bitstreams.headers.description": { + "message": "विवरण" + }, + "item.edit.bitstreams.headers.format": { + "message": "प्रारूप" + }, + "item.edit.bitstreams.headers.name": { + "message": "नाम" + }, + "item.edit.bitstreams.notifications.discarded.content": { + "message": "आपके परिवर्तन खारिज कर दिए गए थे। अपने परिवर्तनों को बहाल करने के लिए 'पूर्ववत करें' बटन पर क्लिक करें" + }, + "item.edit.bitstreams.notifications.discarded.title": { + "message": "परिवर्तन रद्द किये गए" + }, + "item.edit.bitstreams.notifications.move.failed.title": { + "message": "बिटस्ट्रीम ले जाने में त्रुटि" + }, + "item.edit.bitstreams.notifications.move.saved.content": { + "message": "इस आइटम की बिटस्ट्रीम और बंडल में आपके द्वारा किए गए परिवर्तन सहेज लिए गए हैं।" + }, + "item.edit.bitstreams.notifications.move.saved.title": { + "message": "सहेजे गए परिवर्तनों को स्थानांतरित करें" + }, + "item.edit.bitstreams.notifications.outdated.content": { + "message": "जिस आइटम पर आप वर्तमान में काम कर रहे हैं, उसे किसी अन्य उपयोगकर्ता ने बदल दिया है। संघर्षों को रोकने के लिए आपके वर्तमान परिवर्तन खारिज कर दिए गए हैं" + }, + "item.edit.bitstreams.notifications.outdated.title": { + "message": "कालग्रस्त परिवर्तन" + }, + "item.edit.bitstreams.notifications.remove.failed.title": { + "message": "बिटस्ट्रीम हटाने में त्रुटि" + }, + "item.edit.bitstreams.notifications.remove.saved.content": { + "message": "इस आइटम की बिटस्ट्रीम में आपके निष्कासन परिवर्तन सहेज लिए गए हैं।" + }, + "item.edit.bitstreams.notifications.remove.saved.title": { + "message": "हटाए जाने के बदलाव सहेजे गए" + }, + "item.edit.bitstreams.reinstate-button": { + "message": "पूर्ववत करें" + }, + "item.edit.bitstreams.save-button": { + "message": "सहेजें" + }, + "item.edit.bitstreams.upload-button": { + "message": "अपलोड करें" + }, + "item.edit.breadcrumbs": { + "message": "आइटम संपादित करें" + }, + "item.edit.delete.cancel": { + "message": "रद्द करें" + }, + "item.edit.delete.confirm": { + "message": "हटाएं" + }, + "item.edit.delete.description": { + "message": "क्या आप सुनिश्चित हैं कि यह आइटम पूरी तरह से हटा दिया जाना चाहिए? सावधानी: वर्तमान में कोई tombstone नहीं छोड़ा जाएगा।" + }, + "item.edit.delete.error": { + "message": "आइटम को हटाते समय कोई त्रुटि उत्पन्न हुई" + }, + "item.edit.delete.header": { + "message": "आइटम हटाएं: {{id}}" + }, + "item.edit.delete.success": { + "message": "आइटम हटा दिया गया है" + }, + "item.edit.head": { + "message": "आइटम संपादित करें" + }, + "item.edit.item-mapper.buttons.add": { + "message": "आइटम को चयनित संग्रहों में मैप करें" + }, + "item.edit.item-mapper.buttons.remove": { + "message": "चयनित संग्रहों के लिए आइटम की मैपिंग निकालें" + }, + "item.edit.item-mapper.cancel": { + "message": "रद्द करें" + }, + "item.edit.item-mapper.description": { + "message": "यह आइटम मैपर टूल है जो प्रशासकों को इस आइटम को अन्य संग्रहों में मैप करने की अनुमति देता है। आप संग्रहों की खोज कर सकते हैं और उन्हें मैप कर सकते हैं, या उन संग्रहों की सूची ब्राउज़ कर सकते हैं जिनसे आइटम वर्तमान में मैप किया गया है।" + }, + "item.edit.item-mapper.head": { + "message": "आइटम मैपर - संग्रह के लिए आइटम मैप करें" + }, + "item.edit.item-mapper.item": { + "message": "आइटम: \"{{name}}\"" + }, + "item.edit.item-mapper.no-search": { + "message": "खोज करने के लिए कृपया एक प्रश्न दर्ज करें" + }, + "item.edit.item-mapper.notifications.add.error.content": { + "message": "{{amount}} आइटम को संग्रहों में मैप करने में त्रुटियाँ हुईं।" + }, + "item.edit.item-mapper.notifications.add.error.head": { + "message": "मैपिंग त्रुटियाँ" + }, + "item.edit.item-mapper.notifications.add.success.content": { + "message": "{{amount}} आइटम को संग्रह में सफलतापूर्वक मैप किया गया।" + }, + "item.edit.item-mapper.notifications.add.success.head": { + "message": "मैपिंग पूरी हुई" + }, + "item.edit.item-mapper.notifications.remove.error.content": { + "message": "मैपिंग को {{amount}} संग्रह से निकालने में त्रुटियां हुईं." + }, + "item.edit.item-mapper.notifications.remove.error.head": { + "message": "मैपिंग हटाने में त्रुटियां" + }, + "item.edit.item-mapper.notifications.remove.success.content": { + "message": "{{amount}} संग्रह में आइटम की मैपिंग सफलतापूर्वक निकाली गई।" + }, + "item.edit.item-mapper.notifications.remove.success.head": { + "message": "मैपिंग को हटाना पूरा हुआ" + }, + "item.edit.item-mapper.search-form.placeholder": { + "message": "संग्रह में खोजें... " + }, + "item.edit.item-mapper.tabs.browse": { + "message": "मैप किए गए संग्रह ब्राउज़ करें" + }, + "item.edit.item-mapper.tabs.map": { + "message": "नए संग्रहों को मैप करें" + }, + "item.edit.metadata.add-button": { + "message": "जोड़ें" + }, + "item.edit.metadata.discard-button": { + "message": "रद्द करें" + }, + "item.edit.metadata.edit.buttons.edit": { + "message": "संपादित करें" + }, + "item.edit.metadata.edit.buttons.remove": { + "message": "हटाएं" + }, + "item.edit.metadata.edit.buttons.undo": { + "message": "परिवर्तन पूर्ववत करें" + }, + "item.edit.metadata.edit.buttons.unedit": { + "message": "संपादन बंद करें" + }, + "item.edit.metadata.empty": { + "message": "आइटम में वर्तमान में कोई मेटाडेटा नहीं है। मेटाडेटा मान जोड़ना प्रारंभ करने के लिए जोड़ें पर क्लिक करें।" + }, + "item.edit.metadata.headers.edit": { + "message": "संपादित करें" + }, + "item.edit.metadata.headers.field": { + "message": "फील्ड" + }, + "item.edit.metadata.headers.language": { + "message": "भाषा" + }, + "item.edit.metadata.headers.value": { + "message": "मान" + }, + "item.edit.metadata.metadatafield.invalid": { + "message": "कृपया वैध मेटाडेटा फ़ील्ड चुनें" + }, + "item.edit.metadata.notifications.discarded.content": { + "message": "आपके परिवर्तन खारिज कर दिए गए थे। अपने परिवर्तनों को बहाल करने के लिए 'पूर्ववत करें' बटन पर क्लिक करें" + }, + "item.edit.metadata.notifications.discarded.title": { + "message": "परिवर्तन रद्द किये गए" + }, + "item.edit.metadata.notifications.error.title": { + "message": "एक त्रुटि पाई गई" + }, + "item.edit.metadata.notifications.invalid.content": { + "message": "आपके परिवर्तन सहेजे नहीं गए थे। कृपया सुनिश्चित करें कि आपके द्वारा सहेजने से पहले सभी फ़ील्ड मान्य हैं।" + }, + "item.edit.metadata.notifications.invalid.title": { + "message": "मेटाडेटा अमान्य" + }, + "item.edit.metadata.notifications.outdated.content": { + "message": "जिस आइटम पर आप वर्तमान में काम कर रहे हैं, उसे किसी अन्य उपयोगकर्ता ने बदल दिया है। संघर्षों को रोकने के लिए आपके वर्तमान परिवर्तन खारिज कर दिए गए हैं" + }, + "item.edit.metadata.notifications.outdated.title": { + "message": "पुराना बदल गया" + }, + "item.edit.metadata.notifications.saved.content": { + "message": "इस आइटम के मेटाडेटा में आपके परिवर्तन सहेजे गए थे।" + }, + "item.edit.metadata.notifications.saved.title": { + "message": "मेटाडेटा सहेजा गया" + }, + "item.edit.metadata.reinstate-button": { + "message": "पूर्ववत करें" + }, + "item.edit.metadata.save-button": { + "message": "सहेजें" + }, + "item.edit.modify.overview.field": { + "message": "फ़ील्ड" + }, + "item.edit.modify.overview.language": { + "message": "भाषा" + }, + "item.edit.modify.overview.value": { + "message": "मान" + }, + "item.edit.move.cancel": { + "message": "वापस" + }, + "item.edit.move.description": { + "message": "उस संग्रह का चयन करें जिसमें आप इस आइटम को ले जाना चाहते हैं। प्रदर्शित संग्रहों की सूची को छोटा करने के लिए, आप बॉक्स में खोज क्वेरी दर्ज कर सकते हैं।" + }, + "item.edit.move.discard-button": { + "message": "रद्द करें" + }, + "item.edit.move.error": { + "message": "आइटम को स्थानांतरित करने का प्रयास करते समय कोई त्रुटि उत्पन्न हुई" + }, + "item.edit.move.head": { + "message": "आइटम का स्थान परिवर्तन: {{id}}" + }, + "item.edit.move.inheritpolicies.checkbox": { + "message": "नीतियां विरासत में लो" + }, + "item.edit.move.inheritpolicies.description": { + "message": "गंतव्य संग्रह की डिफ़ॉल्ट नीतियों को इनहेरिट करें" + }, + "item.edit.move.move": { + "message": "स्थान परिवर्तन" + }, + "item.edit.move.processing": { + "message": "चल रहा है..." + }, + "item.edit.move.save-button": { + "message": "सहेजें" + }, + "item.edit.move.search.placeholder": { + "message": "संग्रह देखने के लिए एक खोज क्वेरी दर्ज करें" + }, + "item.edit.move.success": { + "message": "आइटम को सफलतापूर्वक स्थानांतरित कर दिया गया है" + }, + "item.edit.move.title": { + "message": "आइटम स्थानांतरण" + }, + "item.edit.private.cancel": { + "message": "रद्द करें" + }, + "item.edit.private.confirm": { + "message": "इसे गैर-खोज योग्य बनाएं" + }, + "item.edit.private.description": { + "message": "क्या आप सुनिश्चित हैं कि इस आइटम को संग्रह में खोजने योग्य नहीं बनाया जाना चाहिए?" + }, + "item.edit.private.error": { + "message": "आइटम को गैर-खोज योग्य बनाते समय एक त्रुटि हुई" + }, + "item.edit.private.header": { + "message": "आइटम को खोजने योग्य न बनाएं: {{ id }}" + }, + "item.edit.private.success": { + "message": "आइटम अब खोजने योग्य नहीं है" + }, + "item.edit.public.cancel": { + "message": "रद्द करें" + }, + "item.edit.public.confirm": { + "message": "इसे खोजने योग्य बनाएं" + }, + "item.edit.public.description": { + "message": "क्या आप इस आइटम को संग्रह में खोजने योग्य बनाने के लिए सुनिश्चित हैं?" + }, + "item.edit.public.error": { + "message": "आइटम को खोजने योग्य बनाते समय एक त्रुटि हुई" + }, + "item.edit.public.header": { + "message": "आइटम को खोजने योग्य बनाएं: {{ id }}" + }, + "item.edit.public.success": { + "message": "आइटम अब खोजने योग्य है" + }, + "item.edit.reinstate.cancel": { + "message": "रद्द करें" + }, + "item.edit.reinstate.confirm": { + "message": "पुनर्स्थापित करें" + }, + "item.edit.reinstate.description": { + "message": "क्या आप इस आइटम को संग्रह में पुनर्स्थापित करने के लिए सुनिश्चित हैं?" + }, + "item.edit.reinstate.error": { + "message": "आइटम को पुनर्स्थापित करते समय एक त्रुटि हुई" + }, + "item.edit.reinstate.header": { + "message": "पुनर्स्थापित आइटम: {{ id }}" + }, + "item.edit.reinstate.success": { + "message": "आइटम को सफलतापूर्वक बहाल कर दिया गया" + }, + "item.edit.relationships.discard-button": { + "message": "रद्द करें" + }, + "item.edit.relationships.edit.buttons.add": { + "message": "जोड़ें" + }, + "item.edit.relationships.edit.buttons.remove": { + "message": "हटाएं" + }, + "item.edit.relationships.edit.buttons.undo": { + "message": "परिवर्तन रद्द किये गए" + }, + "item.edit.relationships.no-entity-type": { + "message": "इस आइटम के लिए संबंध सक्षम करने के लिए 'dspace.entity.type' मेटाडेटा जोड़ें" + }, + "item.edit.relationships.no-relationships": { + "message": "कोई रिश्ता नहीं" + }, + "item.edit.relationships.notifications.discarded.content": { + "message": "आपके परिवर्तन खारिज कर दिए गए थे। अपने परिवर्तनों को बहाल करने के लिए 'पूर्ववत करें' बटन पर क्लिक करें" + }, + "item.edit.relationships.notifications.discarded.title": { + "message": "परिवर्तन रद्द किये गए" + }, + "item.edit.relationships.notifications.failed.title": { + "message": "संबंध संपादित करने में त्रुटि" + }, + "item.edit.relationships.notifications.outdated.content": { + "message": "जिस आइटम पर आप वर्तमान में काम कर रहे हैं, उसे किसी अन्य उपयोगकर्ता ने बदल दिया है। संघर्षों को रोकने के लिए आपके वर्तमान परिवर्तन खारिज कर दिए गए हैं" + }, + "item.edit.relationships.notifications.outdated.title": { + "message": "परिवर्तन पुराना" + }, + "item.edit.relationships.notifications.saved.content": { + "message": "इस आइटम के संबंधों में आपके परिवर्तन सहेज लिए गए थे|" + }, + "item.edit.relationships.notifications.saved.title": { + "message": "रिश्ते सहेजे गए" + }, + "item.edit.relationships.reinstate-button": { + "message": "पूर्ववत करें" + }, + "item.edit.relationships.save-button": { + "message": "सहेजें" + }, + "item.edit.return": { + "message": "वापस" + }, + "item.edit.tabs.bitstreams.head": { + "message": "बिटस्ट्रीम" + }, + "item.edit.tabs.bitstreams.title": { + "message": "आइटम संपादन - बिटस्ट्रीम" + }, + "item.edit.tabs.curate.head": { + "message": "क्यूरेट" + }, + "item.edit.tabs.curate.title": { + "message": "आइटम संपादन - क्यूरेट " + }, + "item.edit.tabs.disabled.tooltip": { + "message": "आप इस टैब में प्रवेश करने के लिए अधिकृत नहीं हैं" + }, + "item.edit.tabs.item-mapper.title": { + "message": "आइटम संपादन - संग्रह मैपर" + }, + "item.edit.tabs.mapper.head": { + "message": "संग्रह मैपर" + }, + "item.edit.tabs.metadata.head": { + "message": "मेटाडेटा" + }, + "item.edit.tabs.metadata.title": { + "message": "आइटम संपादन - मेटाडेटा" + }, + "item.edit.tabs.relationships.head": { + "message": "संबंध" + }, + "item.edit.tabs.relationships.title": { + "message": "आइटम संपादन - संबंध" + }, + "item.edit.tabs.status.buttons.authorizations.button": { + "message": "प्राधिकरण..." + }, + "item.edit.tabs.status.buttons.authorizations.label": { + "message": "आइटम की प्राधिकरण नीतियां संपादित करें" + }, + "item.edit.tabs.status.buttons.delete.button": { + "message": "स्थायी रूप से हटाना" + }, + "item.edit.tabs.status.buttons.delete.label": { + "message": "आइटम को पूरी तरह से मिटाएं" + }, + "item.edit.tabs.status.buttons.mappedCollections.button": { + "message": "मैप किए गए संग्रह" + }, + "item.edit.tabs.status.buttons.mappedCollections.label": { + "message": "मैप किए गए संग्रह प्रबंधित करें" + }, + "item.edit.tabs.status.buttons.move.button": { + "message": "स्थान परिवर्तन..." + }, + "item.edit.tabs.status.buttons.move.label": { + "message": "आइटम को दूसरे संग्रह में ले जाएं" + }, + "item.edit.tabs.status.buttons.private.button": { + "message": "इसे गैर-खोज योग्य बनाएं..." + }, + "item.edit.tabs.status.buttons.private.label": { + "message": "आइटम को गैर-खोज योग्य बनाएं" + }, + "item.edit.tabs.status.buttons.public.button": { + "message": "इसे खोजने योग्य बनाएं..." + }, + "item.edit.tabs.status.buttons.public.label": { + "message": "आइटम को खोजने योग्य बनाएं" + }, + "item.edit.tabs.status.buttons.reinstate.button": { + "message": "पुनर्स्थापित करें..." + }, + "item.edit.tabs.status.buttons.reinstate.label": { + "message": "आइटम को संग्रह में पुनर्स्थापित करें" + }, + "item.edit.tabs.status.buttons.unauthorized": { + "message": "आप इस क्रिया को करने के लिए अधिकृत नहीं हैं" + }, + "item.edit.tabs.status.buttons.withdraw.button": { + "message": "वापस लें..." + }, + "item.edit.tabs.status.buttons.withdraw.label": { + "message": "संग्रहालय से आइटम वापस लेना" + }, + "item.edit.tabs.status.description": { + "message": "आइटम प्रबंधन पृष्ठ पर आपका स्वागत है। यहां से आप आइटम को वापस ले सकते हैं, बहाल कर सकते हैं, स्थानांतरित कर सकते हैं या हटा सकते हैं। आप अन्य टैब पर नए मेटाडेटा / बिटस्ट्रीम को भी अपडेट या जोड़ सकते हैं।" + }, + "item.edit.tabs.status.head": { + "message": "स्थिति" + }, + "item.edit.tabs.status.labels.handle": { + "message": "हैंडल" + }, + "item.edit.tabs.status.labels.id": { + "message": "आइटम का आंतरिक आईडी" + }, + "item.edit.tabs.status.labels.itemPage": { + "message": "आइटम पृष्ठ" + }, + "item.edit.tabs.status.labels.lastModified": { + "message": "अंतिम संशोधित" + }, + "item.edit.tabs.status.title": { + "message": "आइटम संपादन - स्थिति" + }, + "item.edit.tabs.versionhistory.head": { + "message": "संस्करण इतिहास" + }, + "item.edit.tabs.versionhistory.title": { + "message": "आइटम संपादन - संस्करण इतिहास " + }, + "item.edit.tabs.versionhistory.under-construction": { + "message": "इस उपयोगकर्ता इंटरफ़ेस में अभी तक नए संस्करण संपादित करना या जोड़ना संभव नहीं है।" + }, + "item.edit.tabs.view.head": { + "message": "आइटम देखें" + }, + "item.edit.tabs.view.title": { + "message": "आइटम संपादन - देखें" + }, + "item.edit.withdraw.cancel": { + "message": "रद्द करें" + }, + "item.edit.withdraw.confirm": { + "message": "वापस ले" + }, + "item.edit.withdraw.description": { + "message": "क्या आप सुनिश्चित हैं कि इस आइटम को संग्रह से वापस ले लिया जाना चाहिए?" + }, + "item.edit.withdraw.error": { + "message": "आइटम वापस लेते समय एक त्रुटि हुई" + }, + "item.edit.withdraw.header": { + "message": "आइटम वापस ले: {{ id }}" + }, + "item.edit.withdraw.success": { + "message": "आइटम सफलतापूर्वक वापस ले लिया गया" + }, + "item.listelement.badge": { + "message": "आइटम" + }, + "item.orcid.return": { + "message": "वापस" + }, + "item.page.abstract": { + "message": "सारांश" + }, + "item.page.author": { + "message": "लेखक" + }, + "item.page.bitstreams.collapse": { + "message": "संक्षिप्त करें" + }, + "item.page.bitstreams.view-more": { + "message": "और दिखाएं" + }, + "item.page.citation": { + "message": "उद्धरण" + }, + "item.page.claim.button": { + "message": "दावा" + }, + "item.page.claim.tooltip": { + "message": "इस आइटम को प्रोफ़ाइल के रूप में दावा करें" + }, + "item.page.collections": { + "message": "संग्रह" + }, + "item.page.collections.load-more": { + "message": "और लोड करें" + }, + "item.page.collections.loading": { + "message": "लोड हो रहा है..." + }, + "item.page.date": { + "message": "दिनांक" + }, + "item.page.description": { + "message": "विवरण" + }, + "item.page.edit": { + "message": "इस आइटम को संपादित करें" + }, + "item.page.files": { + "message": "फ़ाइलें" + }, + "item.page.filesection.description": { + "message": "विवरण:" + }, + "item.page.filesection.download": { + "message": "डाउनलोड" + }, + "item.page.filesection.format": { + "message": "प्रारूप:" + }, + "item.page.filesection.license.bundle": { + "message": "लाइसेंस बंडल" + }, + "item.page.filesection.name": { + "message": "नाम:" + }, + "item.page.filesection.original.bundle": { + "message": "मूल बंडल" + }, + "item.page.filesection.size": { + "message": "आकार:" + }, + "item.page.journal-issn": { + "message": "जर्नल आईएसएसएन (ISSN)" + }, + "item.page.journal-title": { + "message": "पत्रिका शीर्षक" + }, + "item.page.journal.search.title": { + "message": "इस पत्रिका में लेख" + }, + "item.page.link.full": { + "message": "संपूर्ण आइटम पृष्ठ" + }, + "item.page.link.simple": { + "message": "साधारण आइटम पृष्ठ" + }, + "item.page.orcid.title": { + "message": "ORCID" + }, + "item.page.orcid.tooltip": { + "message": "ORCID सेटिंग पृष्ठ खोलें" + }, + "item.page.person.search.title": { + "message": "इस लेखक के लेख" + }, + "item.page.publisher": { + "message": "प्रकाशक" + }, + "item.page.related-items.view-less": { + "message": "{{ amount }} पिछला छिपाएं " + }, + "item.page.related-items.view-more": { + "message": "{{ amount }} और दिखाएं" + }, + "item.page.relationships.isAuthorOfPublication": { + "message": "प्रकाशन" + }, + "item.page.relationships.isJournalOfPublication": { + "message": "प्रकाशन" + }, + "item.page.relationships.isOrgUnitOfPerson": { + "message": "लेखक" + }, + "item.page.relationships.isOrgUnitOfProject": { + "message": "अनुसंधान परियोजना" + }, + "item.page.return": { + "message": "वापस" + }, + "item.page.subject": { + "message": "खोजशब्द" + }, + "item.page.titleprefix": { + "message": "आइटम: " + }, + "item.page.uri": { + "message": "URI" + }, + "item.page.version.create": { + "message": "नया संस्करण बनाएं" + }, + "item.page.version.hasDraft": { + "message": "नया संस्करण नहीं बनाया जा सकता क्योंकि संस्करण इतिहास में एक प्रगतिशील प्रस्तुति है " + }, + "item.page.volume-title": { + "message": "अंक शीर्षक" + }, + "item.preview.dc.contributor.author": { + "message": "लेखक:" + }, + "item.preview.dc.coverage.spatial": { + "message": "अधिकार - क्षेत्र:" + }, + "item.preview.dc.date.issued": { + "message": "प्रकाशन की तारीख:" + }, + "item.preview.dc.description.abstract": { + "message": "सारांश:" + }, + "item.preview.dc.identifier.one": { + "message": null + }, + "item.preview.dc.identifier.other": { + "message": "Other identifier:" + }, + "item.preview.dc.identifier.zero": { + "message": "अन्य पहचानकर्ता:" + }, + "item.preview.dc.identifier.doi": { + "message": "डीओआई (DOI)" + }, + "item.preview.dc.identifier.isbn": { + "message": "ISBN" + }, + "item.preview.dc.identifier.uri": { + "message": "पहचानकर्ता:" + }, + "item.preview.dc.language.iso": { + "message": "भाषा:" + }, + "item.preview.dc.relation.ispartof": { + "message": "पत्रिका या श्रृंखला" + }, + "item.preview.dc.relation.issn": { + "message": "ISSN" + }, + "item.preview.dc.subject": { + "message": "विषय:" + }, + "item.preview.dc.title": { + "message": "शीर्षक:" + }, + "item.preview.dc.title.alternative": { + "message": "परिवर्णी शब्द:" + }, + "item.preview.dc.type": { + "message": "प्रकार:" + }, + "item.preview.oaire.awardNumber": { + "message": "निधि पहचान:" + }, + "item.preview.oaire.citation.issue": { + "message": "अंक" + }, + "item.preview.oaire.citation.volume": { + "message": "खंड" + }, + "item.preview.oaire.fundingStream": { + "message": "निधि धारा:" + }, + "item.preview.person.familyName": { + "message": "उपनाम:" + }, + "item.preview.person.givenName": { + "message": "नाम:" + }, + "item.preview.person.identifier.orcid": { + "message": "ORCID:" + }, + "item.preview.project.funder.identifier": { + "message": "निधिदाता की पहचान:" + }, + "item.preview.project.funder.name": { + "message": "निधिदाता:" + }, + "item.search.results.head": { + "message": "आइटम खोज परिणाम" + }, + "item.search.title": { + "message": "आइटम खोज" + }, + "item.select.confirm": { + "message": "चयनित की पुष्टि करें" + }, + "item.select.empty": { + "message": "दिखाने के लिए कोई आइटम नहीं है" + }, + "item.select.table.author": { + "message": "लेखक" + }, + "item.select.table.collection": { + "message": "संग्रह" + }, + "item.select.table.title": { + "message": "शीर्षक" + }, + "item.truncatable-part.show-less": { + "message": "संक्षिप्त करें" + }, + "item.truncatable-part.show-more": { + "message": "और दिखाएं" + }, + "item.version.create.modal.button.cancel": { + "message": "रद्द करें" + }, + "item.version.create.modal.button.cancel.tooltip": { + "message": "नया संस्करण न बनाएं" + }, + "item.version.create.modal.button.confirm": { + "message": "बनाएं" + }, + "item.version.create.modal.button.confirm.tooltip": { + "message": "नया संस्करण बनाएं" + }, + "item.version.create.modal.form.summary.label": { + "message": "Summary" + }, + "item.version.create.modal.form.summary.placeholder": { + "message": "नए संस्करण के लिए सारांश डालें" + }, + "item.version.create.modal.header": { + "message": "नया संस्करण" + }, + "item.version.create.modal.submitted.header": { + "message": "नया संस्करण बनाया जा रहा है..." + }, + "item.version.create.modal.submitted.text": { + "message": "नया संस्करण बनाया जा रहा है। यदि आइटम में बहुत अधिक संबंध हैं तो इसमें कुछ समय लग सकता है।" + }, + "item.version.create.modal.text": { + "message": "इस आइटम के लिए एक नया संस्करण बनाएं" + }, + "item.version.create.modal.text.startingFrom": { + "message": "{{version}} संस्करण से प्रारंभ" + }, + "item.version.create.notification.failure": { + "message": "नया संस्करण नहीं बनाया गया है" + }, + "item.version.create.notification.inProgress": { + "message": "एक नया संस्करण नहीं बनाया जा सकता क्योंकि संस्करण इतिहास में एक प्रगतिशील प्रस्तुति है" + }, + "item.version.create.notification.success": { + "message": "संस्करण संख्या {{version}} के साथ नया संस्करण बनाया गया है" + }, + "item.version.delete.modal.button.cancel": { + "message": "रद्द करें" + }, + "item.version.delete.modal.button.cancel.tooltip": { + "message": "इस संस्करण को न हटाएं" + }, + "item.version.delete.modal.button.confirm": { + "message": "हटाएं" + }, + "item.version.delete.modal.button.confirm.tooltip": { + "message": "इस संस्करण को हटाएं" + }, + "item.version.delete.modal.header": { + "message": "संस्करण हटाएं" + }, + "item.version.delete.modal.text": { + "message": "क्या आप संस्करण {{version}} को हटाना चाहते हैं?" + }, + "item.version.delete.notification.failure": { + "message": "संस्करण संख्या {{version}} को हटाया नहीं गया है" + }, + "item.version.delete.notification.success": { + "message": "संस्करण संख्या {{version}} हटा दिया गया है" + }, + "item.version.edit.notification.failure": { + "message": "संस्करण संख्या {{version}} का सारांश नहीं बदला गया है" + }, + "item.version.edit.notification.success": { + "message": "संस्करण संख्या {{version}} का सारांश बदल दिया गया है" + }, + "item.version.history.empty": { + "message": "इस आइटम के लिए अभी तक कोई अन्य संस्करण नहीं हैं।" + }, + "item.version.history.head": { + "message": "संस्करण इतिहास" + }, + "item.version.history.return": { + "message": "वापस" + }, + "item.version.history.selected": { + "message": "चयनित संस्करण" + }, + "item.version.history.selected.alert": { + "message": "आप वर्तमान में आइटम का {{version}} संस्करण देख रहे हैं।" + }, + "item.version.history.table.action.deleteVersion": { + "message": "संस्करण हटाएं" + }, + "item.version.history.table.action.discardSummary": { + "message": "सारांश सम्पादनों को रद्द करें" + }, + "item.version.history.table.action.editSummary": { + "message": "सारांश संपादित करें" + }, + "item.version.history.table.action.editWorkspaceItem": { + "message": "कार्यक्षेत्र आइटम संपादित करें" + }, + "item.version.history.table.action.hasDraft": { + "message": "एक नया संस्करण नहीं बनाया जा सकता क्योंकि संस्करण इतिहास में एक प्रगतिशील प्रस्तुति है" + }, + "item.version.history.table.action.newVersion": { + "message": "इससे नया संस्करण बनाएं" + }, + "item.version.history.table.action.saveSummary": { + "message": "सारांश संपादन सहेजें" + }, + "item.version.history.table.actions": { + "message": "गतिविधि" + }, + "item.version.history.table.date": { + "message": "तारीख" + }, + "item.version.history.table.editor": { + "message": "संपादक" + }, + "item.version.history.table.item": { + "message": "आइटम" + }, + "item.version.history.table.summary": { + "message": "सारांश" + }, + "item.version.history.table.version": { + "message": "संस्करण" + }, + "item.version.history.table.workflowItem": { + "message": "कार्यप्रवाह आइटम" + }, + "item.version.history.table.workspaceItem": { + "message": "कार्यक्षेत्र आइटम" + }, + "item.version.notice": { + "message": "यह इस आइटम का नवीनतम संस्करण नहीं है। नवीनतम संस्करण यहां पाया जा सकता है।" + }, + "journal-relationships.search.results.head": { + "message": "पत्रिका खोज परिणाम" + }, + "journal.listelement.badge": { + "message": "पत्रिका" + }, + "journal.page.description": { + "message": "विवरण" + }, + "journal.page.edit": { + "message": "इस आइटम को संपादित करें" + }, + "journal.page.editor": { + "message": "मुख्या संपादक" + }, + "journal.page.issn": { + "message": "ISSN" + }, + "journal.page.publisher": { + "message": "प्रकाशक" + }, + "journal.page.titleprefix": { + "message": "पत्रिका: " + }, + "journal.search.results.head": { + "message": "पत्रिका खोज परिणाम" + }, + "journal.search.title": { + "message": "पत्रिका खोज" + }, + "journalissue.listelement.badge": { + "message": "पत्रिका अंक" + }, + "journalissue.page.description": { + "message": "विवरण" + }, + "journalissue.page.edit": { + "message": "इस आइटम को संपादित करें" + }, + "journalissue.page.issuedate": { + "message": "जारी करने की तिथि" + }, + "journalissue.page.journal-issn": { + "message": "पत्रिका ISSN" + }, + "journalissue.page.journal-title": { + "message": "पत्रिका का शीर्षक" + }, + "journalissue.page.keyword": { + "message": "खोजशब्द" + }, + "journalissue.page.number": { + "message": "संख्या" + }, + "journalissue.page.titleprefix": { + "message": "पत्रिका अंक:" + }, + "journalvolume.listelement.badge": { + "message": "पत्रिका खंड" + }, + "journalvolume.page.description": { + "message": "विवरण" + }, + "journalvolume.page.edit": { + "message": "इस आइटम को संपादित करें" + }, + "journalvolume.page.issuedate": { + "message": "जारी करने की तिथि" + }, + "journalvolume.page.titleprefix": { + "message": "पत्रिका खंड: " + }, + "journalvolume.page.volume": { + "message": "खंड" + }, + "layouts.application.about": { + "message": "के संबंध में" + }, + "layouts.application.account": { + "message": "खाता" + }, + "layouts.application.app_store": { + "message": "ऐप स्टोर" + }, + "layouts.application.imprint": { + "message": "छाप" + }, + "layouts.application.logout": { + "message": "लॉग आउट" + }, + "layouts.application.my_mails": { + "message": "मेरे मेल" + }, + "layouts.application.press": { + "message": "प्रेस" + }, + "layouts.application.preview": { + "message": "पूर्वावलोकन" + }, + "layouts.application.profile": { + "message": "प्रोफ़ाइल" + }, + "layouts.application.sign_in": { + "message": "लॉग इन करें" + }, + "layouts.application.sign_up": { + "message": "पंजीकृत करें " + }, + "loading.bitstream": { + "message": "बिटस्ट्रीम लोड हो रहा है..." + }, + "loading.bitstreams": { + "message": "बिटस्ट्रीम लोड हो रहा है..." + }, + "loading.browse-by": { + "message": "लोड हो रहा है आइटम..." + }, + "loading.browse-by-page": { + "message": "पृष्ठ लोड हो रहा है..." + }, + "loading.collection": { + "message": "संग्रह लोड हो रहा है..." + }, + "loading.collections": { + "message": "संग्रह लोड हो रहे हैं..." + }, + "loading.community": { + "message": "समुदाय लोड हो रहा है..." + }, + "loading.content-source": { + "message": "सामग्री स्रोत लोड हो रहा है..." + }, + "loading.default": { + "message": "लोड हो रहा है..." + }, + "loading.item": { + "message": "आइटम लोड हो रहा है..." + }, + "loading.items": { + "message": "आइटम लोड हो रहे हैं..." + }, + "loading.mydspace-results": { + "message": "आइटम लोड हो रहे हैं..." + }, + "loading.objects": { + "message": "लोड हो रहा है..." + }, + "loading.recent-submissions": { + "message": "हाल ही की प्रस्तुतियाँ लोड हो रही हैं..." + }, + "loading.search-results": { + "message": "खोज परिणाम लोड हो रहे हैं..." + }, + "loading.sub-collections": { + "message": "उप-संग्रह लोड हो रहा है..." + }, + "loading.sub-communities": { + "message": "उप-समुदाय लोड हो रहे हैं..." + }, + "loading.top-level-communities": { + "message": "शीर्ष-स्तरीय समुदाय लोड हो रहे हैं..." + }, + "login.breadcrumbs": { + "message": "लॉग इन करें" + }, + "login.form.email": { + "message": "ईमेल पता" + }, + "login.form.forgot-password": { + "message": "क्या आप अपना पासवर्ड भूल गए हैं?" + }, + "login.form.header": { + "message": "कृपया डीस्पेस में लॉग इन करें" + }, + "login.form.new-user": { + "message": "नया उपयोगकर्ता? पंजीकरण करने के लिए यहां क्लिक करें।" + }, + "login.form.oidc": { + "message": "ओआईडीसी (OIDC) के साथ लॉग इन करें" + }, + "login.form.or-divider": { + "message": "अथवा" + }, + "login.form.orcid": { + "message": "ORCID के साथ लॉग इन करें" + }, + "login.form.password": { + "message": "पासवर्ड" + }, + "login.form.shibboleth": { + "message": "शिबोलेथ के साथ लॉग इन करें" + }, + "login.form.submit": { + "message": "लॉग इन करें" + }, + "login.title": { + "message": "लॉग इन करें" + }, + "logout.form.header": { + "message": "डीस्पेस से लॉग आउट करें" + }, + "logout.form.submit": { + "message": "लॉग आउट करें" + }, + "logout.title": { + "message": "लॉग आउट" + }, + "media-viewer.next": { + "message": "अगला" + }, + "media-viewer.playlist": { + "message": "प्लेलिस्ट" + }, + "media-viewer.previous": { + "message": "पिछला" + }, + "menu.header.admin": { + "message": "प्रबंधन" + }, + "menu.header.admin.description": { + "message": "प्रबंधन मेनू" + }, + "menu.header.image.logo": { + "message": "संग्रहालय चिन्ह" + }, + "menu.section.access_control": { + "message": "अभिगम नियंत्रण" + }, + "menu.section.access_control_authorizations": { + "message": "प्राधिकरण" + }, + "menu.section.access_control_groups": { + "message": "समूह" + }, + "menu.section.access_control_people": { + "message": "लोग" + }, + "menu.section.admin_search": { + "message": "व्यवस्थापक खोज" + }, + "menu.section.browse_community": { + "message": "यह समुदाय" + }, + "menu.section.browse_community_by_author": { + "message": "लेखक द्वारा" + }, + "menu.section.browse_community_by_issue_date": { + "message": "जारी करने की तिथि के अनुसार" + }, + "menu.section.browse_community_by_title": { + "message": "शीर्षक के द्वारा" + }, + "menu.section.browse_global": { + "message": "सम्पूर्ण डीस्पेस" + }, + "menu.section.browse_global_by_author": { + "message": "लेखक द्वारा" + }, + "menu.section.browse_global_by_dateissued": { + "message": "जारी करने की तिथि के द्वारा" + }, + "menu.section.browse_global_by_subject": { + "message": "विषय द्वारा" + }, + "menu.section.browse_global_by_title": { + "message": "शीर्षक द्वारा" + }, + "menu.section.browse_global_communities_and_collections": { + "message": "समुदाय और संग्रह" + }, + "menu.section.control_panel": { + "message": "नियंत्रण कक्ष" + }, + "menu.section.curation_task": { + "message": "क्यूरेशन टास्क" + }, + "menu.section.edit": { + "message": "संपादित करें" + }, + "menu.section.edit_collection": { + "message": "संग्रह" + }, + "menu.section.edit_community": { + "message": "समुदाय" + }, + "menu.section.edit_item": { + "message": "आइटम" + }, + "menu.section.export": { + "message": "निर्यात करें" + }, + "menu.section.export_collection": { + "message": "संग्रह" + }, + "menu.section.export_community": { + "message": "समुदाय" + }, + "menu.section.export_item": { + "message": "आइटम" + }, + "menu.section.export_metadata": { + "message": "मेटाडेटा" + }, + "menu.section.health": { + "message": "स्वास्थ्य" + }, + "menu.section.icon.access_control": { + "message": "अभिगम नियंत्रण मेन्यू अनुभाग" + }, + "menu.section.icon.admin_search": { + "message": "व्यवस्थापक खोज मेनू अनुभाग" + }, + "menu.section.icon.control_panel": { + "message": "नियंत्रण कक्ष मेन्यू अनुभाग" + }, + "menu.section.icon.curation_tasks": { + "message": "अवधि कार्य मेनू अनुभाग" + }, + "menu.section.icon.edit": { + "message": "मेन्यू अनुभाग संपादित करें" + }, + "menu.section.icon.export": { + "message": "निर्यात मेनू अनुभाग" + }, + "menu.section.icon.find": { + "message": "मेनू अनुभाग खोजें" + }, + "menu.section.icon.health": { + "message": "स्वास्थ्य जांच मेनू अनुभाग" + }, + "menu.section.icon.import": { + "message": "आयात मेनू अनुभाग" + }, + "menu.section.icon.new": { + "message": "नया मेनू अनुभाग" + }, + "menu.section.icon.pin": { + "message": "साइडबार पिन करें" + }, + "menu.section.icon.processes": { + "message": "प्रक्रिया स्वास्थ्य" + }, + "menu.section.icon.registries": { + "message": "रजिस्ट्रियां मेन्यू अनुभाग" + }, + "menu.section.icon.statistics_task": { + "message": "सांख्यिकी कार्य मेनू अनुभाग" + }, + "menu.section.icon.unpin": { + "message": "साइडबार अनपिन करें" + }, + "menu.section.icon.workflow": { + "message": "कार्यप्रवाह मेनू अनुभाग का व्यवस्थापन करें" + }, + "menu.section.import": { + "message": "आयात" + }, + "menu.section.import_batch": { + "message": "खेप आयात (ZIP)" + }, + "menu.section.import_metadata": { + "message": "मेटाडाटा " + }, + "menu.section.new": { + "message": "नया" + }, + "menu.section.new_collection": { + "message": "संग्रह" + }, + "menu.section.new_community": { + "message": "समुदाय" + }, + "menu.section.new_item": { + "message": "आइटम" + }, + "menu.section.new_item_version": { + "message": "आइटम संस्करण" + }, + "menu.section.new_process": { + "message": "प्रक्रिया" + }, + "menu.section.pin": { + "message": "साइडबार नत्थी करें" + }, + "menu.section.processes": { + "message": "प्रक्रियाएं" + }, + "menu.section.registries": { + "message": "रजिस्ट्री" + }, + "menu.section.registries_format": { + "message": "प्रारूप" + }, + "menu.section.registries_metadata": { + "message": "मेटाडाटा" + }, + "menu.section.statistics": { + "message": "सांख्यिकी" + }, + "menu.section.statistics_task": { + "message": "सांख्यिकी कार्य" + }, + "menu.section.toggle.access_control": { + "message": "अभिगम नियंत्रण अनुभाग टॉगल करें" + }, + "menu.section.toggle.control_panel": { + "message": "नियंत्रण कक्ष अनुभाग टॉगल करें" + }, + "menu.section.toggle.curation_task": { + "message": "क्यूरेशन कार्य अनुभाग टॉगल करें " + }, + "menu.section.toggle.edit": { + "message": "संपादन कार्य अनुभाग टॉगल करें " + }, + "menu.section.toggle.export": { + "message": "निर्यात कार्य अनुभाग टॉगल करें " + }, + "menu.section.toggle.find": { + "message": "अनुभाग खोजें टॉगल करें" + }, + "menu.section.toggle.import": { + "message": "आयात अनुभाग टॉगल करें" + }, + "menu.section.toggle.new": { + "message": "नया अनुभाग टॉगल करें" + }, + "menu.section.toggle.registries": { + "message": "रजिस्ट्री अनुभाग टॉगल करें" + }, + "menu.section.toggle.statistics_task": { + "message": "सांख्यिकी कार्य अनुभाग टॉगल करें" + }, + "menu.section.unpin": { + "message": "साइडबार अनपिन करें" + }, + "menu.section.workflow": { + "message": "कार्यप्रवाह व्यवस्थापित करें" + }, + "metadata-export-search.submit.error": { + "message": "निर्यात प्रारंभ करना विफल रहा" + }, + "metadata-export-search.submit.success": { + "message": "निर्यात सफलतापूर्वक शुरू किया गया था" + }, + "metadata-export-search.tooltip": { + "message": "खोज परिणामों को CSV के रूप में निर्यात करें" + }, + "mydspace.breadcrumbs": { + "message": "मेरा डीस्पेस" + }, + "mydspace.description": { + "message": null + }, + "mydspace.general.text-here": { + "message": "यहां" + }, + "mydspace.messages.controller-help": { + "message": "आइटम के प्रस्तुतकर्ता को संदेश भेजने के लिए इस विकल्प का चयन करें।" + }, + "mydspace.messages.description-placeholder": { + "message": "अपना संदेश यहां डालें..." + }, + "mydspace.messages.hide-msg": { + "message": "संदेश छुपाएं" + }, + "mydspace.messages.mark-as-read": { + "message": "पढ़ा गया के रूप में चिह्नित करें" + }, + "mydspace.messages.mark-as-unread": { + "message": "अपठित के रूप में चिह्नित करें" + }, + "mydspace.messages.no-content": { + "message": "कोई सामग्री नहीं है।" + }, + "mydspace.messages.no-messages": { + "message": "अभी तक कोई संदेश नहीं।" + }, + "mydspace.messages.send-btn": { + "message": "भेजें" + }, + "mydspace.messages.show-msg": { + "message": "संदेश दिखाएँ" + }, + "mydspace.messages.subject-placeholder": { + "message": "विषय..." + }, + "mydspace.messages.submitter-help": { + "message": "नियंत्रक को संदेश भेजने के लिए इस विकल्प का चयन करें।" + }, + "mydspace.messages.title": { + "message": "संदेश" + }, + "mydspace.messages.to": { + "message": "तक" + }, + "mydspace.new-submission": { + "message": "नया प्रस्तुतीकरण" + }, + "mydspace.new-submission-external": { + "message": "बाहरी स्रोत से मेटाडेटा आयात करें" + }, + "mydspace.new-submission-external-short": { + "message": "मेटाडेटा आयात करें" + }, + "mydspace.results.head": { + "message": "आपकी प्रस्तुतियाँ" + }, + "mydspace.results.no-abstract": { + "message": "कोई सार नहीं" + }, + "mydspace.results.no-authors": { + "message": "कोई लेखक नहीं" + }, + "mydspace.results.no-collections": { + "message": "कोई संग्रह नहीं" + }, + "mydspace.results.no-date": { + "message": "कोई तारीख नहीं" + }, + "mydspace.results.no-files": { + "message": "कोई फाइल नहीं" + }, + "mydspace.results.no-results": { + "message": "दिखाने के लिए कोई आइटम नहीं थे" + }, + "mydspace.results.no-title": { + "message": "कोई शीर्षक नहीं" + }, + "mydspace.results.no-uri": { + "message": "Uri नहीं है" + }, + "mydspace.search-form.placeholder": { + "message": "मेरे डीस्पेस में खोजें..." + }, + "mydspace.show.workflow": { + "message": "कार्यप्रवाह कार्य" + }, + "mydspace.show.workspace": { + "message": "आपकी प्रस्तुतियां" + }, + "mydspace.status.archived": { + "message": "संग्रहीत" + }, + "mydspace.status.validation": { + "message": "सत्यापन" + }, + "mydspace.status.waiting-for-controller": { + "message": "नियंत्रक की प्रतीक्षा कर रहा है" + }, + "mydspace.status.workflow": { + "message": "कार्यप्रवाह" + }, + "mydspace.status.workspace": { + "message": "कार्यस्थान" + }, + "mydspace.title": { + "message": "मेरा डीस्पेस" + }, + "mydspace.upload.upload-failed": { + "message": "नया कार्यस्थान बनाने में त्रुटि. कृपया पुनः प्रयास करने से पहले अपलोड की गई सामग्री को सत्यापित करें।" + }, + "mydspace.upload.upload-failed-manyentries": { + "message": "असंसाधित फ़ाइल। बहुत अधिक प्रविष्टियों का पता लगाया लेकिन फ़ाइल के लिए केवल एक की अनुमति दी।" + }, + "mydspace.upload.upload-failed-moreonefile": { + "message": "असंसाधित अनुरोध। केवल एक फ़ाइल की अनुमति है।" + }, + "mydspace.upload.upload-multiple-successful": { + "message": "{{qty}} नए कार्यक्षेत्र आइटम बनाए गए।" + }, + "mydspace.upload.upload-successful": { + "message": "नया कार्यस्थान आइटम बनाया गया। इसे संपादित करने के लिए {{here}} क्लिक करें।" + }, + "mydspace.view-btn": { + "message": "देखें" + }, + "nav.browse.header": { + "message": "सम्पूर्ण डीस्पेस" + }, + "nav.community-browse.header": { + "message": "समुदाय द्वारा" + }, + "nav.language": { + "message": "भाषा स्विच" + }, + "nav.login": { + "message": "लॉग इन करें" + }, + "nav.logout": { + "message": "उपयोगकर्ता प्रोफ़ाइल मेनू और लॉग आउट" + }, + "nav.main.description": { + "message": "मुख्य नेविगेशन बार" + }, + "nav.mydspace": { + "message": "मेरा डीस्पेस" + }, + "nav.profile": { + "message": "प्रोफ़ाइल" + }, + "nav.search": { + "message": "खोजें" + }, + "nav.statistics.header": { + "message": "सांख्यिकी" + }, + "nav.stop-impersonating": { + "message": "ई-व्यक्ति का रूप धारण करना बंद करें" + }, + "nav.toggle": { + "message": "नेविगेशन टॉगल करें" + }, + "nav.user.description": { + "message": "उपयोगकर्ता प्रोफ़ाइल बार" + }, + "none.listelement.badge": { + "message": "आइटम" + }, + "orgunit.listelement.badge": { + "message": "संगठित इकाई" + }, + "orgunit.page.city": { + "message": "शहर" + }, + "orgunit.page.country": { + "message": "देश" + }, + "orgunit.page.dateestablished": { + "message": "स्थापना की तिथि" + }, + "orgunit.page.description": { + "message": "विवरण" + }, + "orgunit.page.edit": { + "message": "इस आइटम को संपादित करें" + }, + "orgunit.page.id": { + "message": "पहचान" + }, + "orgunit.page.titleprefix": { + "message": "संगठनात्मक इकाइयाँ: " + }, + "pagination.next.button": { + "message": "अगला" + }, + "pagination.next.button.disabled.tooltip": { + "message": "परिणामों के और पृष्ठ नहीं" + }, + "pagination.options.description": { + "message": "पृष्ठांकन के विकल्प" + }, + "pagination.previous.button": { + "message": "पिछला" + }, + "pagination.results-per-page": { + "message": "प्रति पृष्ठ परिणाम" + }, + "pagination.showing.detail": { + "message": "{{ range }} में से {{ total }}" + }, + "pagination.showing.label": { + "message": "अब दिखा रहे हैं" + }, + "pagination.sort-direction": { + "message": "क्रमबद्ध विकल्प" + }, + "person-relationships.search.results.head": { + "message": "व्यक्ति खोज परिणाम" + }, + "person.listelement.badge": { + "message": "व्यक्ति" + }, + "person.listelement.no-title": { + "message": "कोई नाम नहीं मिला" + }, + "person.orcid.registry.auth": { + "message": "ORCID प्राधिकरण" + }, + "person.orcid.registry.queue": { + "message": "ORCID रजिस्ट्री कतार" + }, + "person.orcid.sync.setting": { + "message": "ORCID तुल्यकालन सेटिंग्स" + }, + "person.page.birthdate": { + "message": "जन्म तिथि" + }, + "person.page.edit": { + "message": "इस आइटम को संपादित करें" + }, + "person.page.email": { + "message": "ईमेल पता" + }, + "person.page.firstname": { + "message": "पहला नाम" + }, + "person.page.jobtitle": { + "message": "नौकरी का शीर्षक" + }, + "person.page.lastname": { + "message": "उपनाम" + }, + "person.page.link.full": { + "message": "सभी मेटाडेटा दिखाएं" + }, + "person.page.name": { + "message": "नाम" + }, + "person.page.orcid": { + "message": "ORCID" + }, + "person.page.orcid.create": { + "message": "एक ORCID आईडी बनाएं" + }, + "person.page.orcid.funding-preferences": { + "message": "वित्त पोषण प्राथमिकताएं" + }, + "person.page.orcid.grant-authorizations": { + "message": "अनुदान प्राधिकरण" + }, + "person.page.orcid.granted-authorizations": { + "message": "स्वीकृत प्राधिकरण" + }, + "person.page.orcid.link": { + "message": "ORCID आईडी से जोड़े" + }, + "person.page.orcid.link.error.message": { + "message": "प्रोफ़ाइल को ORCID से जोड़ते समय कोई गड़बड़ी हुई। यदि समस्या बनी रहती है, तो व्यवस्थापक से संपर्क करें।" + }, + "person.page.orcid.link.processing": { + "message": "प्रोफ़ाइल को ORCID से लिंक किया जा रहा है..." + }, + "person.page.orcid.missing-authorizations": { + "message": "गुम अनुमति" + }, + "person.page.orcid.missing-authorizations-message": { + "message": "निम्नलिखित प्राधिकरण गायब हैं:" + }, + "person.page.orcid.no-missing-authorizations-message": { + "message": "आपको आपके संस्थान द्वारा सभी फ़ंक्शन का उपयोग करने के लिए एक्सेस अधिकार दिए गए हैं, इसलिए यह बॉक्स खाली है!" + }, + "person.page.orcid.no-orcid-message": { + "message": "अभी तक कोई ORCID iD संबद्ध नहीं है। नीचे दिए गए बटन पर क्लिक करके इस प्रोफाइल को ओआरसीआईडी खाते से लिंक करना संभव है।" + }, + "person.page.orcid.orcid-not-linked-message": { + "message": "इस प्रोफ़ाइल की ORCID iD ({{orcid }}) अभी तक ORCID रजिस्ट्री पर किसी खाते से कनेक्ट नहीं हुई है या कनेक्शन की समय-सीमा समाप्त हो गई है।" + }, + "person.page.orcid.profile-preferences": { + "message": "प्रोफाइल प्राथमिकताएं" + }, + "person.page.orcid.publications-preferences": { + "message": "प्रकाशन प्राथमिकताएं" + }, + "person.page.orcid.remove-orcid-message": { + "message": "यदि आपको अपना ORCID हटाना है, तो कृपया संग्रहालय व्यवस्थापक से संपर्क करें" + }, + "person.page.orcid.save.preference.changes": { + "message": "सेटिंग अद्यतन करें" + }, + "person.page.orcid.scope.activities-update": { + "message": "अपनी शोध गतिविधियों को जोड़ें/अपडेट करें" + }, + "person.page.orcid.scope.authenticate": { + "message": "अपना ORCID आईडी प्राप्त करें" + }, + "person.page.orcid.scope.person-update": { + "message": "अपने बारे में अन्य जानकारी जोड़ें/अपडेट करें" + }, + "person.page.orcid.scope.read-limited": { + "message": "विश्वसनीय पक्षों पर सेट दृश्यता के साथ अपनी जानकारी पढ़ें" + }, + "person.page.orcid.sync-fundings.all": { + "message": "सारे निधि स्त्रोत " + }, + "person.page.orcid.sync-fundings.disabled": { + "message": "अक्षम" + }, + "person.page.orcid.sync-fundings.mine": { + "message": "मेरे निधि स्त्रोत " + }, + "person.page.orcid.sync-fundings.my_selected": { + "message": "चयनित निधि स्त्रोत" + }, + "person.page.orcid.sync-profile.affiliation": { + "message": "संबद्धता" + }, + "person.page.orcid.sync-profile.biographical": { + "message": "जीवनी डेटा" + }, + "person.page.orcid.sync-profile.education": { + "message": "शिक्षण" + }, + "person.page.orcid.sync-profile.identifiers": { + "message": "पहचानकर्ता" + }, + "person.page.orcid.sync-publications.all": { + "message": "सभी प्रकाशन" + }, + "person.page.orcid.sync-publications.disabled": { + "message": "निर्योग्य" + }, + "person.page.orcid.sync-publications.mine": { + "message": "मेरे प्रकाशन" + }, + "person.page.orcid.sync-publications.my_selected": { + "message": "चयनित प्रकाशन" + }, + "person.page.orcid.sync-queue.description.affiliation": { + "message": "संबद्धता" + }, + "person.page.orcid.sync-queue.description.country": { + "message": "देश" + }, + "person.page.orcid.sync-queue.description.education": { + "message": "शिक्षण" + }, + "person.page.orcid.sync-queue.description.external_ids": { + "message": "बाहरी आईडी" + }, + "person.page.orcid.sync-queue.description.keywords": { + "message": "खोजशब्द" + }, + "person.page.orcid.sync-queue.description.other_names": { + "message": "अन्य नाम" + }, + "person.page.orcid.sync-queue.description.qualification": { + "message": "योग्यता" + }, + "person.page.orcid.sync-queue.description.researcher_urls": { + "message": "अनुसंधानकर्ता यूआरएल (URLs)" + }, + "person.page.orcid.sync-queue.discard": { + "message": "परिवर्तन छोड़ें और ORCID रजिस्ट्री के साथ सिंक्रनाइज़ न करें" + }, + "person.page.orcid.sync-queue.discard.error": { + "message": "ORCID कतार रिकॉर्ड को हटाना विफल रहा" + }, + "person.page.orcid.sync-queue.discard.success": { + "message": "ORCID कतार रिकॉर्ड को सफलतापूर्वक खारिज कर दिया गया है" + }, + "person.page.orcid.sync-queue.empty-message": { + "message": "ORCID रजिस्ट्री कतार खाली है" + }, + "person.page.orcid.sync-queue.send": { + "message": "ORCID रजिस्ट्री के साथ सिंक्रनाइज़ करें" + }, + "person.page.orcid.sync-queue.send.bad-request-error": { + "message": "ORCID को प्रस्तुतीकरण विफल हुआ क्योंकि ORCID रजिस्ट्री को भेजा गया संसाधन मान्य नहीं है" + }, + "person.page.orcid.sync-queue.send.conflict-error": { + "message": "ORCID को प्रस्तुतीकरण विफल रहा क्योंकि संसाधन ORCID रजिस्ट्री पर पहले से मौजूद है" + }, + "person.page.orcid.sync-queue.send.error": { + "message": "ORCID को प्रस्तुतीकरण विफल रहा" + }, + "person.page.orcid.sync-queue.send.not-found-warning": { + "message": "संसाधन अब ORCID रजिस्ट्री पर मौजूद नहीं है।" + }, + "person.page.orcid.sync-queue.send.success": { + "message": "ORCID को प्रस्तुतीकरण सफलतापूर्वक पूरा किया गया " + }, + "person.page.orcid.sync-queue.send.unauthorized-error.content": { + "message": "फिर से आवश्यक अनुमतियां देने के लिए यहां क्लिक करें। यदि समस्या बनी रहती है, तो व्यवस्थापक से संपर्क करें।" + }, + "person.page.orcid.sync-queue.send.unauthorized-error.title": { + "message": "ORCID को प्रस्तुतीकरण अनुपलब्ध प्राधिकरणों के कारण विफल रहा।" + }, + "person.page.orcid.sync-queue.send.validation-error": { + "message": "जिस डेटा को आप ORCID के साथ सिंक्रोनाइज़ करना चाहते हैं वह मान्य नहीं है" + }, + "person.page.orcid.sync-queue.send.validation-error.amount-currency.required": { + "message": "राशि की मुद्रा आवश्यक है" + }, + "person.page.orcid.sync-queue.send.validation-error.country.invalid": { + "message": "अमान्य 2 अंक ISO 3166 देश" + }, + "person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.required": { + "message": "संगठनों को स्पष्ट करने के लिए एक पहचानकर्ता की आवश्यकता है। समर्थित आईडी जीआरआईडी, रिंगगोल्ड, कानूनी इकाई पहचानकर्ता (एलईआई) और क्रॉसरेफ फंडर रजिस्ट्री पहचानकर्ता हैं" + }, + "person.page.orcid.sync-queue.send.validation-error.disambiguated-organization.value-required": { + "message": "संगठन के पहचानकर्ताओं को एक मूल्य की आवश्यकता है" + }, + "person.page.orcid.sync-queue.send.validation-error.disambiguation-source.invalid": { + "message": "संगठन पहचानकर्ताओं में से एक का स्रोत अमान्य है। समर्थित स्रोत हैं RINGGOLD, GRID, LEI और FUNDREF" + }, + "person.page.orcid.sync-queue.send.validation-error.disambiguation-source.required": { + "message": "संगठन के पहचानकर्ताओं को स्रोत की आवश्यकता होती है" + }, + "person.page.orcid.sync-queue.send.validation-error.external-id.required": { + "message": "भेजे जाने वाले संसाधन के लिए कम से कम एक पहचानकर्ता की आवश्यकता होती है" + }, + "person.page.orcid.sync-queue.send.validation-error.funder.required": { + "message": "धन की आवश्यकता है" + }, + "person.page.orcid.sync-queue.send.validation-error.organization.address-required": { + "message": "भेजे जाने वाले संगठन को पते की आवश्यकता है" + }, + "person.page.orcid.sync-queue.send.validation-error.organization.city-required": { + "message": "भेजे जाने वाले संगठन के पते के लिए एक शहर की आवश्यकता है" + }, + "person.page.orcid.sync-queue.send.validation-error.organization.country-required": { + "message": "भेजे जाने वाले संगठन के पते के लिए मान्य 2 अंकों वाला ISO 3166 देश होना चाहिए" + }, + "person.page.orcid.sync-queue.send.validation-error.organization.name-required": { + "message": "संगठन का नाम आवश्यक है" + }, + "person.page.orcid.sync-queue.send.validation-error.organization.required": { + "message": "संगठन की आवश्यकता है" + }, + "person.page.orcid.sync-queue.send.validation-error.publication.date-invalid": { + "message": "प्रकाशन की तारीख 1900 . के एक साल बाद की होनी चाहिए" + }, + "person.page.orcid.sync-queue.send.validation-error.start-date.required": { + "message": "प्रारंभ दिनांक आवश्यक है" + }, + "person.page.orcid.sync-queue.send.validation-error.title.required": { + "message": "शीर्षक आवश्यक है" + }, + "person.page.orcid.sync-queue.send.validation-error.type.required": { + "message": "dc.type आवश्यक है" + }, + "person.page.orcid.sync-queue.table.header.action": { + "message": "कार्रवाई" + }, + "person.page.orcid.sync-queue.table.header.description": { + "message": "विवरण" + }, + "person.page.orcid.sync-queue.table.header.type": { + "message": "प्रकार" + }, + "person.page.orcid.sync-queue.tooltip.affiliation": { + "message": "संबद्धता" + }, + "person.page.orcid.sync-queue.tooltip.country": { + "message": "देश" + }, + "person.page.orcid.sync-queue.tooltip.delete": { + "message": "इस प्रविष्टि को ORCID रजिस्ट्री से निकालें" + }, + "person.page.orcid.sync-queue.tooltip.education": { + "message": "शिक्षा" + }, + "person.page.orcid.sync-queue.tooltip.external_ids": { + "message": "बाहरी पहचानकर्ता" + }, + "person.page.orcid.sync-queue.tooltip.insert": { + "message": "ORCID रजिस्ट्री में नई प्रविष्टि जोड़ें" + }, + "person.page.orcid.sync-queue.tooltip.keywords": { + "message": "खोजशब्द" + }, + "person.page.orcid.sync-queue.tooltip.other_names": { + "message": "अन्य नाम" + }, + "person.page.orcid.sync-queue.tooltip.project": { + "message": "परियोजना" + }, + "person.page.orcid.sync-queue.tooltip.publication": { + "message": "प्रकाशन" + }, + "person.page.orcid.sync-queue.tooltip.qualification": { + "message": "योग्यता" + }, + "person.page.orcid.sync-queue.tooltip.researcher_urls": { + "message": "अनुसंधानकर्ता url" + }, + "person.page.orcid.sync-queue.tooltip.update": { + "message": "ORCID रजिस्ट्री पर इस प्रविष्टि को अद्यतन करें" + }, + "person.page.orcid.synchronization-mode": { + "message": "तुल्यकालन प्रणाली" + }, + "person.page.orcid.synchronization-mode-funding-message": { + "message": "चुनें कि आपकी लिंक की गई परियोजना संस्थाओं को आपके ORCID रिकॉर्ड की फंडिंग जानकारी की सूची में भेजना है या नहीं।" + }, + "person.page.orcid.synchronization-mode-message": { + "message": "कृपया ORCID के साथ तुल्यकालन (सिंक्रोनाइजेशन) विकल्प चुनें। विकल्पों में \"मानव चलित\" (आपको अपना डेटा अपने आप ORCID को भेजना होगा), या \"बैच\" (सिस्टम आपके डेटा को एक निर्धारित स्क्रिप्ट के माध्यम से ORCID को भेजेगा)।" + }, + "person.page.orcid.synchronization-mode-profile-message": { + "message": "क्या आपका जैविक डेटा या व्यक्तिगत पहचानकर्ता आपके ओआरसीआईडी रिकॉर्ड में भेजना है?" + }, + "person.page.orcid.synchronization-mode-publication-message": { + "message": "चुनें कि आपकी लिंक की गई प्रकाशन इकाइयों को आपके ORCID रिकॉर्ड की कार्यों की सूची में भेजना है या नहीं।" + }, + "person.page.orcid.synchronization-mode.batch": { + "message": "बैच" + }, + "person.page.orcid.synchronization-mode.label": { + "message": "तुल्यकालन प्रणाली" + }, + "person.page.orcid.synchronization-mode.manual": { + "message": "मानव चलित" + }, + "person.page.orcid.synchronization-settings-update.error": { + "message": "तुल्यकालन सेटिंग्स का अद्यतन विफल रहा " + }, + "person.page.orcid.synchronization-settings-update.success": { + "message": "तुल्यकालन सेटिंग्स को सफलतापूर्वक अपडेट कर दिया गया है" + }, + "person.page.orcid.unlink": { + "message": "ORCID से अलग करें" + }, + "person.page.orcid.unlink.error": { + "message": "प्रोफ़ाइल और ORCID रजिस्ट्री को अलग करते समय त्रुटि उत्पन्न हुई। पुनः प्रयास करें" + }, + "person.page.orcid.unlink.processing": { + "message": "संसाधित किया जा रहा है..." + }, + "person.page.orcid.unlink.success": { + "message": "प्रोफ़ाइल और ORCID रजिस्ट्री के बीच वियोग सफल रहा" + }, + "person.page.staffid": { + "message": "कर्मचारी की पहचान" + }, + "person.page.titleprefix": { + "message": "व्यक्ति: " + }, + "person.search.results.head": { + "message": "व्यक्ति खोज परिणाम" + }, + "person.search.title": { + "message": "व्यक्ति की खोज" + }, + "process.detail.arguments": { + "message": "बहस" + }, + "process.detail.arguments.empty": { + "message": "इस प्रक्रिया में कोई तर्क नहीं है" + }, + "process.detail.back": { + "message": "वापस" + }, + "process.detail.create": { + "message": "समान प्रक्रिया बनाएं" + }, + "process.detail.end-time": { + "message": "समाप्ति समय" + }, + "process.detail.logs.button": { + "message": "प्रक्रिया उत्पाद प्राप्त करें " + }, + "process.detail.logs.loading": { + "message": "पुन: र्प्राप्ति जारी है" + }, + "process.detail.logs.none": { + "message": "इस प्रक्रिया का कोई उत्पादन नहीं है" + }, + "process.detail.output": { + "message": "प्रक्रिया उत्पाद" + }, + "process.detail.output-files": { + "message": "आउटपुट फ़ाइलें" + }, + "process.detail.output-files.empty": { + "message": "इस प्रक्रिया में कोई फाइल उत्पादित नहीं हुई है" + }, + "process.detail.script": { + "message": "स्क्रिप्ट" + }, + "process.detail.start-time": { + "message": "प्रारंभ समय" + }, + "process.detail.status": { + "message": "स्थिति" + }, + "process.detail.title": { + "message": "प्रक्रिया: {{ id }} - {{ name }}" + }, + "process.new.breadcrumbs": { + "message": "नई प्रक्रिया बनाएं" + }, + "process.new.cancel": { + "message": "रद्द करें" + }, + "process.new.header": { + "message": "नई प्रक्रिया बनाएं" + }, + "process.new.notification.error.content": { + "message": "इस प्रक्रिया को बनाते समय एक त्रुटि हुई" + }, + "process.new.notification.error.title": { + "message": "त्रुटि" + }, + "process.new.notification.success.content": { + "message": "प्रक्रिया सफलतापूर्वक बनाई गई" + }, + "process.new.notification.success.title": { + "message": "सफलता" + }, + "process.new.parameter.file.required": { + "message": "कृपया एक फ़ाइल चुनें" + }, + "process.new.parameter.file.upload-button": { + "message": "फ़ाइल का चयन करें..." + }, + "process.new.parameter.required.missing": { + "message": "निम्नलिखित पैरामीटर आवश्यक हैं लेकिन अभी भी गायब हैं:" + }, + "process.new.parameter.string.required": { + "message": "पैरामीटर मान आवश्यक है" + }, + "process.new.parameter.type.file": { + "message": "फ़ाइल" + }, + "process.new.parameter.type.value": { + "message": "मान" + }, + "process.new.select-parameters": { + "message": "मापदंड" + }, + "process.new.select-script": { + "message": "स्क्रिप्ट" + }, + "process.new.select-script.placeholder": { + "message": "स्क्रिप्ट चुनें..." + }, + "process.new.select-script.required": { + "message": "स्क्रिप्ट की आवश्यकता है" + }, + "process.new.submit": { + "message": "सहेजें" + }, + "process.new.title": { + "message": "एक नई प्रक्रिया बनाएं" + }, + "process.overview.breadcrumbs": { + "message": "प्रक्रियाओं का अवलोकन" + }, + "process.overview.new": { + "message": "नया" + }, + "process.overview.table.finish": { + "message": "समाप्ति समय (UTC)" + }, + "process.overview.table.id": { + "message": "प्रक्रिया पहचान क्रमांक" + }, + "process.overview.table.name": { + "message": "नाम" + }, + "process.overview.table.start": { + "message": "प्रारंभ समय (UTC)" + }, + "process.overview.table.status": { + "message": "स्थिति" + }, + "process.overview.table.user": { + "message": "उपयोगकर्ता" + }, + "process.overview.title": { + "message": "प्रक्रिया अवलोकन" + }, + "profile.breadcrumbs": { + "message": "प्रोफ़ाइल को नवीनतम बनाएं" + }, + "profile.card.identify": { + "message": "पहचान" + }, + "profile.card.researcher": { + "message": "अनुसंधानकर्ता प्रोफाइल" + }, + "profile.card.security": { + "message": "सुरक्षा" + }, + "profile.form.submit": { + "message": "सहेजें" + }, + "profile.groups.head": { + "message": "आप जिस प्राधिकरण समूह से संबंधित हैं" + }, + "profile.head": { + "message": "प्रोफ़ाइल को नवीनतम बनाएं" + }, + "profile.metadata.form.error.firstname.required": { + "message": "पहला नाम आवश्यक है" + }, + "profile.metadata.form.error.lastname.required": { + "message": "उपनाम आवश्यक है" + }, + "profile.metadata.form.label.email": { + "message": "ईमेल पता" + }, + "profile.metadata.form.label.firstname": { + "message": "पहला नाम" + }, + "profile.metadata.form.label.language": { + "message": "भाषा" + }, + "profile.metadata.form.label.lastname": { + "message": "उपनाम" + }, + "profile.metadata.form.label.phone": { + "message": "संपर्क टेलीफोन" + }, + "profile.metadata.form.notifications.success.content": { + "message": "प्रोफ़ाइल में आपके परिवर्तन सहेजे गए थे।" + }, + "profile.metadata.form.notifications.success.title": { + "message": "प्रोफाइल सहेजा गया" + }, + "profile.notifications.warning.no-changes.content": { + "message": "प्रोफाइल में कोई बदलाव नहीं किया गया।" + }, + "profile.notifications.warning.no-changes.title": { + "message": "कोई बदलाव नहीं" + }, + "profile.security.form.error.matching-passwords": { + "message": "पासवर्ड एक - दूसरे से मिलते - जुलते नहीं हैं।" + }, + "profile.security.form.error.password-length": { + "message": "पासवर्ड कम से कम 6 अक्षर लंबा होना चाहिए।" + }, + "profile.security.form.info": { + "message": "वैकल्पिक रूप से, आप नीचे दिए गए बॉक्स में नया पासवर्ड दर्ज कर सकते हैं, और इसे दूसरे बॉक्स में फिर से टाइप करके इसकी पुष्टि करें। यह कम से कम छह वर्ण लंबा होना चाहिए।" + }, + "profile.security.form.label.password": { + "message": "पासवर्ड" + }, + "profile.security.form.label.passwordrepeat": { + "message": "पुष्टि करने के लिए फिर से लिखें" + }, + "profile.security.form.notifications.error.not-long-enough": { + "message": "पासवर्ड कम से कम 6 अक्षर लंबा होना चाहिए।" + }, + "profile.security.form.notifications.error.not-same": { + "message": "प्रदान किए गए पासवर्ड समान नहीं हैं।" + }, + "profile.security.form.notifications.error.title": { + "message": "पासवर्ड बदलने में त्रुटि" + }, + "profile.security.form.notifications.success.content": { + "message": "पासवर्ड में आपके परिवर्तन सहेजे गए थे।" + }, + "profile.security.form.notifications.success.title": { + "message": "पासवर्ड सहेजा गया" + }, + "profile.special.groups.head": { + "message": "विशेष समूह प्राधिकरण जिनसे आप संबंधित हैं" + }, + "profile.title": { + "message": "प्रोफ़ाइल को नवीनतम बनाएं" + }, + "project-relationships.search.results.head": { + "message": "परियोजना खोज परिणाम" + }, + "project.listelement.badge": { + "message": "अनुसंधान परियोजना" + }, + "project.page.contributor": { + "message": "योगदानकर्ता" + }, + "project.page.description": { + "message": "विवरण" + }, + "project.page.edit": { + "message": "इस आइटम को संपादित करें" + }, + "project.page.expectedcompletion": { + "message": "पूरा होने की उम्मीद" + }, + "project.page.funder": { + "message": "निधिदाता" + }, + "project.page.id": { + "message": "पहचान" + }, + "project.page.keyword": { + "message": "खोजशब्द" + }, + "project.page.status": { + "message": "स्थिति" + }, + "project.page.titleprefix": { + "message": "अनुसंधान परियोजना:" + }, + "project.search.results.head": { + "message": "परियोजना खोज परिणाम" + }, + "publication-relationships.search.results.head": { + "message": "प्रकाशन खोज परिणाम" + }, + "publication.listelement.badge": { + "message": "प्रकाशन" + }, + "publication.page.description": { + "message": "विवरण" + }, + "publication.page.edit": { + "message": "इस आइटम को संपादित करें" + }, + "publication.page.journal-issn": { + "message": "पत्रिका ISSN" + }, + "publication.page.journal-title": { + "message": "पत्रिका शीर्षक" + }, + "publication.page.publisher": { + "message": "प्रकाशक" + }, + "publication.page.titleprefix": { + "message": "प्रकाशन:" + }, + "publication.page.volume-title": { + "message": "अंक शीर्षक" + }, + "publication.search.results.head": { + "message": "प्रकाशन खोज परिणाम" + }, + "publication.search.title": { + "message": "प्रकाशन खोज" + }, + "register-email.title": { + "message": "नया उपयोगकर्ता पंजीकरण" + }, + "register-page.create-profile.header": { + "message": "प्रोफ़ाइल बनाएं" + }, + "register-page.create-profile.identification.contact": { + "message": "संपर्क टेलीफोन" + }, + "register-page.create-profile.identification.email": { + "message": "ईमेल पता" + }, + "register-page.create-profile.identification.first-name": { + "message": "पहला नाम *" + }, + "register-page.create-profile.identification.first-name.error": { + "message": "कृपया पहला नाम भरें" + }, + "register-page.create-profile.identification.header": { + "message": "पहचान करें " + }, + "register-page.create-profile.identification.language": { + "message": "भाषा" + }, + "register-page.create-profile.identification.last-name": { + "message": "उपनाम *" + }, + "register-page.create-profile.identification.last-name.error": { + "message": "कृपया अंतिम नाम भरें" + }, + "register-page.create-profile.security.error.empty-password": { + "message": "कृपया नीचे दिए गए बॉक्स में पासवर्ड दर्ज करें।" + }, + "register-page.create-profile.security.error.matching-passwords": { + "message": "पासवर्ड एक - दूसरे से मिलते - जुलते नहीं हैं।" + }, + "register-page.create-profile.security.error.password-length": { + "message": "पासवर्ड कम से कम 6 अक्षर लंबा होना चाहिए।" + }, + "register-page.create-profile.security.header": { + "message": "सुरक्षा" + }, + "register-page.create-profile.security.info": { + "message": "कृपया नीचे दिए गए बॉक्स में पासवर्ड दर्ज करें, और दूसरे बॉक्स में फिर से टाइप करके इसकी पुष्टि करें। यह कम से कम छह वर्ण लंबा होना चाहिए।" + }, + "register-page.create-profile.security.label.password": { + "message": "पासवर्ड *" + }, + "register-page.create-profile.security.label.passwordrepeat": { + "message": "पुष्टि करने के लिए फिर से लिखें *" + }, + "register-page.create-profile.submit": { + "message": "पंजीकरण पूर्ण करें" + }, + "register-page.create-profile.submit.error.content": { + "message": "नया उपयोगकर्ता पंजीकृत करते समय कुछ गलत हुआ।" + }, + "register-page.create-profile.submit.error.head": { + "message": "पंजीकरण विफल रहा" + }, + "register-page.create-profile.submit.success.content": { + "message": "पंजीकरण सफल रहा। आपको बनाए गए उपयोगकर्ता के रूप में लॉग इन किया गया है।" + }, + "register-page.create-profile.submit.success.head": { + "message": "पंजीकरण पूर्ण" + }, + "register-page.registration.email": { + "message": "ईमेल पता *" + }, + "register-page.registration.email.error.pattern": { + "message": "कृपया ईमेल पता भरें" + }, + "register-page.registration.email.error.required": { + "message": "कृपया ईमेल पता भरें" + }, + "register-page.registration.email.hint": { + "message": "यह पता सत्यापित किया जाएगा और आपके लॉगिन नाम के रूप में उपयोग किया जाएगा।" + }, + "register-page.registration.error.content": { + "message": "निम्न ईमेल पता पंजीकृत करते समय एक त्रुटि हुई: {{ email }}" + }, + "register-page.registration.error.head": { + "message": "ईमेल पंजीकृत करने का प्रयास करते समय त्रुटि" + }, + "register-page.registration.header": { + "message": "नया उपयोगकर्ता पंजीकरण" + }, + "register-page.registration.info": { + "message": "डीस्पेस में नई प्रस्तुति तथा ईमेल द्वारा संग्रह अद्यतन की जानकारी हेतु सदस्यता के लिए नया खता पंजीकृत करें" + }, + "register-page.registration.submit": { + "message": "पंजीकृत करें " + }, + "register-page.registration.success.content": { + "message": "{{ email }} को एक विशेष यूआरएल और अन्य निर्देशों के साथ एक ईमेल भेजा गया है।" + }, + "register-page.registration.success.head": { + "message": "सत्यापन ईमेल भेज दिया गया है" + }, + "relationships.add.error.relationship-type.content": { + "message": "दो मदों के बीच {{type }} संबंध प्रकार के लिए कोई उपयुक्त मिलान नहीं पाया जा सका" + }, + "relationships.add.error.server.content": { + "message": "सर्वर ने त्रुटि लौटाई" + }, + "relationships.add.error.title": { + "message": "संबंध जोड़ने में असमर्थ" + }, + "relationships.isAuthorOf": { + "message": "लेखक" + }, + "relationships.isAuthorOf.OrgUnit": { + "message": "लेखक (संगठनात्मक इकाइयां)" + }, + "relationships.isAuthorOf.Person": { + "message": "लेखक (व्यक्ति)" + }, + "relationships.isContributorOf": { + "message": "योगदानकर्ता" + }, + "relationships.isContributorOf.OrgUnit": { + "message": "योगदानकर्ता (संगठनात्मक इकाई)" + }, + "relationships.isContributorOf.Person": { + "message": "योगदान देने वाला" + }, + "relationships.isFundingAgencyOf.OrgUnit": { + "message": "निधिदाता" + }, + "relationships.isIssueOf": { + "message": "पत्रिका अंक" + }, + "relationships.isJournalIssueOf": { + "message": "पत्रिका अंक" + }, + "relationships.isJournalOf": { + "message": "पत्रिकाएं" + }, + "relationships.isOrgUnitOf": { + "message": "संगठनात्मक इकाइयाँ" + }, + "relationships.isPersonOf": { + "message": "लेखक" + }, + "relationships.isProjectOf": { + "message": "अनुसंधान परियोजना" + }, + "relationships.isPublicationOf": { + "message": "प्रकाशन" + }, + "relationships.isPublicationOfJournalIssue": { + "message": "लेख" + }, + "relationships.isSingleJournalOf": { + "message": "पत्रिका" + }, + "relationships.isSingleVolumeOf": { + "message": "पत्रिका खंड" + }, + "relationships.isVolumeOf": { + "message": "पत्रिका खंड" + }, + "repository.image.logo": { + "message": "संग्राहलय चिन्ह" + }, + "repository.title.prefix": { + "message": "डीस्पेस एंग्युलर::" + }, + "repository.title.prefixDSpace": { + "message": "डीस्पेस एंग्यूलर ::" + }, + "researcher.profile.action.processing": { + "message": "संसाधित किया जा रहा है..." + }, + "researcher.profile.associated": { + "message": "शोधकर्ता प्रोफ़ाइल संबद्ध" + }, + "researcher.profile.change-visibility.fail": { + "message": "प्रोफ़ाइल दृश्यता बदलते समय एक अनपेक्षित त्रुटि उत्पन्न होती है" + }, + "researcher.profile.create.fail": { + "message": "शोधकर्ता प्रोफ़ाइल निर्माण के दौरान एक त्रुटि उत्पन्न होती है" + }, + "researcher.profile.create.new": { + "message": "नया बनाएं" + }, + "researcher.profile.create.success": { + "message": "अनुसंधानकर्ता प्रोफ़ाइल सफलतापूर्वक बनाई गई" + }, + "researcher.profile.delete": { + "message": "हटाएं" + }, + "researcher.profile.expose": { + "message": "खुलासा" + }, + "researcher.profile.hide": { + "message": "छिपाना" + }, + "researcher.profile.not.associated": { + "message": "अनुसंधानकर्ता प्रोफ़ाइल अभी तक सम्बंधित नहीं है " + }, + "researcher.profile.private.visibility": { + "message": "निजी" + }, + "researcher.profile.public.visibility": { + "message": "सार्वजनिक" + }, + "researcher.profile.status": { + "message": "दर्जा:" + }, + "researcher.profile.view": { + "message": "देखें" + }, + "researcherprofile.claim.not-authorized": { + "message": "आप इस मद पर दावा करने के लिए अधिकृत नहीं हैं। अधिक जानकारी के लिए व्यवस्थापक से संपर्क करें।" + }, + "researcherprofile.error.claim.body": { + "message": "प्रोफ़ाइल का दावा करते समय एक त्रुटि हुई, कृपया बाद में पुन: प्रयास करें" + }, + "researcherprofile.error.claim.title": { + "message": "त्रुटि" + }, + "researcherprofile.success.claim.body": { + "message": "प्रोफ़ाइल पर सफलतापूर्वक दावा किया गया" + }, + "researcherprofile.success.claim.title": { + "message": "सफलता" + }, + "resource-policies.add.button": { + "message": "जोड़ें" + }, + "resource-policies.add.for.": { + "message": "नई नीति जोड़ें" + }, + "resource-policies.add.for.bitstream": { + "message": "एक नई बिटस्ट्रीम नीति जोड़ें" + }, + "resource-policies.add.for.bundle": { + "message": "नई बंडल नीति जोड़ें" + }, + "resource-policies.add.for.collection": { + "message": "एक नई संग्रह नीति जोड़ें" + }, + "resource-policies.add.for.community": { + "message": "नई सामुदायिक नीति जोड़ें" + }, + "resource-policies.add.for.item": { + "message": "नई आइटम नीति जोड़ें" + }, + "resource-policies.create.page.failure.content": { + "message": "संसाधन नीति बनाते समय कोई त्रुटि उत्पन्न हुई।" + }, + "resource-policies.create.page.heading": { + "message": "के लिए नई संसाधन नीति बनाएं" + }, + "resource-policies.create.page.success.content": { + "message": "संचालन सफल रहा" + }, + "resource-policies.create.page.title": { + "message": "नई संसाधन नीति बनाएं" + }, + "resource-policies.delete.btn": { + "message": "चयनित को हटाएं" + }, + "resource-policies.delete.btn.title": { + "message": "चयनित संसाधन नीतियां हटाएं" + }, + "resource-policies.delete.failure.content": { + "message": "चयनित संसाधन नीतियों को हटाते समय एक त्रुटि उत्पन्न हुई।" + }, + "resource-policies.delete.success.content": { + "message": "संचालन सफल रहा" + }, + "resource-policies.edit.page.failure.content": { + "message": "संसाधन नीति संपादित करते समय कोई त्रुटि उत्पन्न हुई।" + }, + "resource-policies.edit.page.heading": { + "message": "संसाधन नीति संपादित करें" + }, + "resource-policies.edit.page.other-failure.content": { + "message": "संसाधन नीति संपादित करते समय कोई त्रुटि उत्पन्न हुई। लक्ष्य (ई-व्यक्ति या समूह) का सफलतापूर्वक अद्यतन कर दिया गया है।" + }, + "resource-policies.edit.page.success.content": { + "message": "संचालन सफल रहा" + }, + "resource-policies.edit.page.target-failure.content": { + "message": "संसाधन नीति के लक्ष्य (ई-व्यक्ति या समूह) को संपादित करते समय कोई त्रुटि उत्पन्न हुई।" + }, + "resource-policies.edit.page.title": { + "message": "संसाधन नीति संपादित करें" + }, + "resource-policies.form.action-type.label": { + "message": "क्रिया प्रकार चुनें" + }, + "resource-policies.form.action-type.required": { + "message": "आपको संसाधन नीति कार्रवाई का चयन करना होगा।" + }, + "resource-policies.form.date.end.label": { + "message": "अंतिम तिथि" + }, + "resource-policies.form.date.start.label": { + "message": "आरंभ करने की तिथि" + }, + "resource-policies.form.description.label": { + "message": "विवरण" + }, + "resource-policies.form.eperson-group-list.label": { + "message": "वह व्यक्ति या समूह जिसे अनुमति दी जाएगी" + }, + "resource-policies.form.eperson-group-list.modal.close": { + "message": "ठीक है" + }, + "resource-policies.form.eperson-group-list.modal.header": { + "message": "प्रकार नहीं बदल सकता" + }, + "resource-policies.form.eperson-group-list.modal.text1.toEPerson": { + "message": "समूह को ई-व्यक्ति से बदलना संभव नहीं है।" + }, + "resource-policies.form.eperson-group-list.modal.text1.toGroup": { + "message": "ई-व्यक्ति को समूह से बदलना संभव नहीं है।" + }, + "resource-policies.form.eperson-group-list.modal.text2": { + "message": "वर्तमान संसाधन नीति हटाएं और वांछित प्रकार के साथ एक नई बनाएं।" + }, + "resource-policies.form.eperson-group-list.select.btn": { + "message": "चयन करें" + }, + "resource-policies.form.eperson-group-list.tab.eperson": { + "message": "ई-व्यक्ति के लिए खोजें" + }, + "resource-policies.form.eperson-group-list.tab.group": { + "message": "एक समूह खोजें" + }, + "resource-policies.form.eperson-group-list.table.headers.action": { + "message": "गतिविधि" + }, + "resource-policies.form.eperson-group-list.table.headers.id": { + "message": "पहचान" + }, + "resource-policies.form.eperson-group-list.table.headers.name": { + "message": "नाम" + }, + "resource-policies.form.name.label": { + "message": "नाम" + }, + "resource-policies.form.policy-type.label": { + "message": "नीति प्रकार चुनें" + }, + "resource-policies.form.policy-type.required": { + "message": "आपको संसाधन नीति प्रकार का चयन करना होगा।" + }, + "resource-policies.table.headers.action": { + "message": "गतिविधि" + }, + "resource-policies.table.headers.date.end": { + "message": "अंतिम तिथि" + }, + "resource-policies.table.headers.date.start": { + "message": "आरंभ तिथि" + }, + "resource-policies.table.headers.edit": { + "message": "संपादित करें" + }, + "resource-policies.table.headers.edit.group": { + "message": "समूह संपादित करें" + }, + "resource-policies.table.headers.edit.policy": { + "message": "नीति संपादित करें" + }, + "resource-policies.table.headers.eperson": { + "message": "ई-व्यक्ति" + }, + "resource-policies.table.headers.group": { + "message": "समूह" + }, + "resource-policies.table.headers.id": { + "message": "पहचान" + }, + "resource-policies.table.headers.name": { + "message": "नाम" + }, + "resource-policies.table.headers.policyType": { + "message": "प्रकार" + }, + "resource-policies.table.headers.title.for.bitstream": { + "message": "बिटस्ट्रीम के लिए नीतियां" + }, + "resource-policies.table.headers.title.for.bundle": { + "message": "बंडल के लिए नीतियां" + }, + "resource-policies.table.headers.title.for.collection": { + "message": "संग्रह के लिए नीतियां" + }, + "resource-policies.table.headers.title.for.community": { + "message": "समुदाय के लिए नीतियां" + }, + "resource-policies.table.headers.title.for.item": { + "message": "आइटम के लिए नीतियां" + }, + "search.breadcrumbs": { + "message": "खोजें" + }, + "search.description": { + "message": null + }, + "search.filters.applied.f.author": { + "message": "लेखक" + }, + "search.filters.applied.f.birthDate.max": { + "message": "अंतिम जन्म तिथि" + }, + "search.filters.applied.f.birthDate.min": { + "message": "जन्म तिथि प्रारंभ करें" + }, + "search.filters.applied.f.dateIssued.max": { + "message": "अंतिम तिथि" + }, + "search.filters.applied.f.dateIssued.min": { + "message": "आरंभ करने की तिथि" + }, + "search.filters.applied.f.dateSubmitted": { + "message": "प्रस्तुत करने की तारीख" + }, + "search.filters.applied.f.discoverable": { + "message": "गैर-खोज योग्य" + }, + "search.filters.applied.f.entityType": { + "message": "आइटम का प्रकार" + }, + "search.filters.applied.f.has_content_in_original_bundle": { + "message": "फ़ाइलें हैं" + }, + "search.filters.applied.f.itemtype": { + "message": "प्रकार" + }, + "search.filters.applied.f.jobTitle": { + "message": "नौकरी का शीर्षक" + }, + "search.filters.applied.f.namedresourcetype": { + "message": "स्थिति" + }, + "search.filters.applied.f.subject": { + "message": "विषय" + }, + "search.filters.applied.f.submitter": { + "message": "प्रस्तुतकर्ता" + }, + "search.filters.applied.f.withdrawn": { + "message": "वापस लिया गया" + }, + "search.filters.discoverable.false": { + "message": "हाँ" + }, + "search.filters.discoverable.true": { + "message": "नहीं" + }, + "search.filters.entityType.JournalIssue": { + "message": "पत्रिका अंक" + }, + "search.filters.entityType.JournalVolume": { + "message": "पत्रिका खंड" + }, + "search.filters.entityType.OrgUnit": { + "message": "संगठित इकाई" + }, + "search.filters.filter.author.head": { + "message": "लेखक" + }, + "search.filters.filter.author.label": { + "message": "लेखक का नाम खोजें" + }, + "search.filters.filter.author.placeholder": { + "message": "लेखक का नाम" + }, + "search.filters.filter.birthDate.head": { + "message": "जन्म तिथि" + }, + "search.filters.filter.birthDate.label": { + "message": "जन्म तिथि खोजें" + }, + "search.filters.filter.birthDate.placeholder": { + "message": "जन्म तिथि" + }, + "search.filters.filter.collapse": { + "message": "फ़िल्टर संक्षिप्त करें" + }, + "search.filters.filter.creativeDatePublished.head": { + "message": "प्रकाशित तिथि" + }, + "search.filters.filter.creativeDatePublished.label": { + "message": "प्रकाशित तिथि पर खोजें" + }, + "search.filters.filter.creativeDatePublished.placeholder": { + "message": "प्रकाशित तिथि" + }, + "search.filters.filter.creativeWorkEditor.head": { + "message": "संपादक" + }, + "search.filters.filter.creativeWorkEditor.label": { + "message": "संपादक खोजें" + }, + "search.filters.filter.creativeWorkEditor.placeholder": { + "message": "संपादक" + }, + "search.filters.filter.creativeWorkKeywords.head": { + "message": "विषय" + }, + "search.filters.filter.creativeWorkKeywords.label": { + "message": "विषय खोजें" + }, + "search.filters.filter.creativeWorkKeywords.placeholder": { + "message": "विषय" + }, + "search.filters.filter.creativeWorkPublisher.head": { + "message": "प्रकाशक" + }, + "search.filters.filter.creativeWorkPublisher.label": { + "message": "प्रकाशक खोजें" + }, + "search.filters.filter.creativeWorkPublisher.placeholder": { + "message": "प्रकाशक" + }, + "search.filters.filter.dateIssued.head": { + "message": "तिथि" + }, + "search.filters.filter.dateIssued.max.label": { + "message": "अंत" + }, + "search.filters.filter.dateIssued.max.placeholder": { + "message": "अधिकतम तिथि" + }, + "search.filters.filter.dateIssued.min.label": { + "message": "शुरू करें" + }, + "search.filters.filter.dateIssued.min.placeholder": { + "message": "न्यूनतम तिथि" + }, + "search.filters.filter.dateSubmitted.head": { + "message": "प्रस्तुत करने की तारीख" + }, + "search.filters.filter.dateSubmitted.label": { + "message": "खोज की तारीख जमा की गई" + }, + "search.filters.filter.dateSubmitted.placeholder": { + "message": "प्रस्तुत करने की तारीख" + }, + "search.filters.filter.discoverable.head": { + "message": "गैर-खोज योग्य" + }, + "search.filters.filter.entityType.head": { + "message": "आइटम का प्रकार" + }, + "search.filters.filter.entityType.label": { + "message": "आइटम प्रकार खोजें" + }, + "search.filters.filter.entityType.placeholder": { + "message": "आइटम का प्रकार" + }, + "search.filters.filter.expand": { + "message": "फ़िल्टर का विस्तार करें" + }, + "search.filters.filter.has_content_in_original_bundle.head": { + "message": "फ़ाइलें हैं" + }, + "search.filters.filter.itemtype.head": { + "message": "प्रकार" + }, + "search.filters.filter.itemtype.label": { + "message": "खोज प्रकार" + }, + "search.filters.filter.itemtype.placeholder": { + "message": "प्रकार" + }, + "search.filters.filter.jobTitle.head": { + "message": "नौकरी का शीर्षक" + }, + "search.filters.filter.jobTitle.label": { + "message": "नौकरी का शीर्षक खोजें" + }, + "search.filters.filter.jobTitle.placeholder": { + "message": "नौकरी का शीर्षक" + }, + "search.filters.filter.knowsLanguage.head": { + "message": "ज्ञात भाषा" + }, + "search.filters.filter.knowsLanguage.label": { + "message": "ज्ञात भाषा खोजें" + }, + "search.filters.filter.knowsLanguage.placeholder": { + "message": "ज्ञात भाषा" + }, + "search.filters.filter.namedresourcetype.head": { + "message": "स्थिति" + }, + "search.filters.filter.namedresourcetype.label": { + "message": "खोज स्थिति" + }, + "search.filters.filter.namedresourcetype.placeholder": { + "message": "स्थिति" + }, + "search.filters.filter.objectpeople.head": { + "message": "लोग" + }, + "search.filters.filter.objectpeople.label": { + "message": "लोगों को खोजें" + }, + "search.filters.filter.objectpeople.placeholder": { + "message": "लोग" + }, + "search.filters.filter.organizationAddressCountry.head": { + "message": "देश" + }, + "search.filters.filter.organizationAddressCountry.label": { + "message": "देश खोजें" + }, + "search.filters.filter.organizationAddressCountry.placeholder": { + "message": "देश" + }, + "search.filters.filter.organizationAddressLocality.head": { + "message": "शहर" + }, + "search.filters.filter.organizationAddressLocality.label": { + "message": "शहर खोजें" + }, + "search.filters.filter.organizationAddressLocality.placeholder": { + "message": "शहर" + }, + "search.filters.filter.organizationFoundingDate.head": { + "message": "स्थापना तिथि" + }, + "search.filters.filter.organizationFoundingDate.label": { + "message": "खोज तिथि मिली" + }, + "search.filters.filter.organizationFoundingDate.placeholder": { + "message": "स्थापना तिथि" + }, + "search.filters.filter.scope.head": { + "message": "क्षेत्र" + }, + "search.filters.filter.scope.label": { + "message": "खोज क्षेत्र फ़िल्टर" + }, + "search.filters.filter.scope.placeholder": { + "message": "स्कोप फिल्टर" + }, + "search.filters.filter.show-less": { + "message": "संक्षिप्त करें" + }, + "search.filters.filter.show-more": { + "message": "और दिखाएं" + }, + "search.filters.filter.subject.head": { + "message": "विषय" + }, + "search.filters.filter.subject.label": { + "message": "विषय खोजें" + }, + "search.filters.filter.subject.placeholder": { + "message": "विषय" + }, + "search.filters.filter.submitter.head": { + "message": "प्रस्तुतकर्ता" + }, + "search.filters.filter.submitter.label": { + "message": "प्रस्तुतकर्ता को खोजें" + }, + "search.filters.filter.submitter.placeholder": { + "message": "प्रस्तुतकर्ता" + }, + "search.filters.filter.withdrawn.head": { + "message": "वापस लिया गया" + }, + "search.filters.has_content_in_original_bundle.false": { + "message": "नहीं" + }, + "search.filters.has_content_in_original_bundle.true": { + "message": "हाँ" + }, + "search.filters.head": { + "message": "फिल्टर" + }, + "search.filters.reset": { + "message": "फ़िल्टर रीसेट करें" + }, + "search.filters.search.submit": { + "message": "प्रस्तुत करें" + }, + "search.filters.withdrawn.false": { + "message": "नहीं" + }, + "search.filters.withdrawn.true": { + "message": "हाँ" + }, + "search.form.scope.all": { + "message": "सम्पूर्ण डीस्पेस" + }, + "search.form.search": { + "message": "खोजें" + }, + "search.form.search_dspace": { + "message": "सम्पूर्ण संग्रहालय" + }, + "search.results.empty": { + "message": "आपकी खोज ने कोई परिणाम नहीं दिया।" + }, + "search.results.head": { + "message": "खोज के परिणाम" + }, + "search.results.no-results": { + "message": "आपकी खोज का कोई परिणाम नहीं निकला। आप जो खोज रहे हैं उसे ढूंढने में परेशानी हो रही है? डालने का प्रयास करें" + }, + "search.results.no-results-link": { + "message": "इसके चारों ओर उद्धरण" + }, + "search.results.view-result": { + "message": "देखें" + }, + "search.search-form.placeholder": { + "message": "संग्रहालय में खोजें ..." + }, + "search.sidebar.close": { + "message": "परिणामों पर वापस जाएं" + }, + "search.sidebar.filters.title": { + "message": "फिल्टर" + }, + "search.sidebar.open": { + "message": "खोज उपकरण" + }, + "search.sidebar.results": { + "message": "परिणाम" + }, + "search.sidebar.settings.rpp": { + "message": "प्रति पृष्ठ परिणाम" + }, + "search.sidebar.settings.sort-by": { + "message": "द्वारा क्रमबद्ध करें" + }, + "search.sidebar.settings.title": { + "message": "समायोजन" + }, + "search.switch-configuration.title": { + "message": "दिखाएँ" + }, + "search.title": { + "message": "खोजें" + }, + "search.view-switch.show-detail": { + "message": "विवरण दिखाएँ" + }, + "search.view-switch.show-grid": { + "message": "ग्रिड के रूप में दिखाएं" + }, + "search.view-switch.show-list": { + "message": "सूची के रूप में दिखाएं" + }, + "sorting.ASC": { + "message": "आरोही" + }, + "sorting.dc.date.accessioned.ASC": { + "message": "परिग्रहण तिथि आरोही" + }, + "sorting.dc.date.accessioned.DESC": { + "message": "परिग्रहण तिथि अवरोही" + }, + "sorting.dc.date.issued.ASC": { + "message": "जारी तिथि आरोही" + }, + "sorting.dc.date.issued.DESC": { + "message": "जारी दिनांक अवरोही" + }, + "sorting.dc.title.ASC": { + "message": "शीर्षक आरोही" + }, + "sorting.dc.title.DESC": { + "message": "शीर्षक अवरोही" + }, + "sorting.DESC": { + "message": "अवरोही" + }, + "sorting.lastModified.ASC": { + "message": "अंतिम संशोधित आरोही" + }, + "sorting.lastModified.DESC": { + "message": "अंतिम संशोधित अवरोही" + }, + "sorting.score.ASC": { + "message": "न्यूनतम प्रासंगिक" + }, + "sorting.score.DESC": { + "message": "सबसे अधिक प्रासंगिक" + }, + "statistics.breadcrumbs": { + "message": "सांख्यिकी" + }, + "statistics.header": { + "message": "{{ scope }} के आंकड़े" + }, + "statistics.page.no-data": { + "message": "कोई डेटा उपलब्ध नहीं" + }, + "statistics.table.header.views": { + "message": "दौरे" + }, + "statistics.table.no-data": { + "message": "कोई डेटा उपलब्ध नहीं" + }, + "statistics.table.title.TopCities": { + "message": "शीर्ष शहर के दृश्य" + }, + "statistics.table.title.TopCountries": { + "message": "शीर्ष दर्शक देश" + }, + "statistics.table.title.TotalDownloads": { + "message": "फ़ाइल का दौरा" + }, + "statistics.table.title.TotalVisits": { + "message": "कुल दौरा" + }, + "statistics.table.title.TotalVisitsPerMonth": { + "message": "प्रति माह कुल विज़िट" + }, + "statistics.title": { + "message": "सांख्यिकी" + }, + "submission.edit.breadcrumbs": { + "message": "प्रस्तुति सम्पादित करें" + }, + "submission.edit.title": { + "message": "प्रस्तुति संपादित करें" + }, + "submission.general.cancel": { + "message": "रद्द करें" + }, + "submission.general.cannot_submit": { + "message": "आपको नई प्रस्तुति करने का विशेषाधिकार नहीं है।" + }, + "submission.general.deposit": { + "message": "जमा" + }, + "submission.general.discard.confirm.cancel": { + "message": "रद्द करें" + }, + "submission.general.discard.confirm.info": { + "message": "यह कार्रवाई पूर्ववत नहीं की जा सकती। क्या आपको यकीन है?" + }, + "submission.general.discard.confirm.submit": { + "message": "हां मुझे यकीन है" + }, + "submission.general.discard.confirm.title": { + "message": "प्रस्तुति रद्द करें" + }, + "submission.general.discard.submit": { + "message": "रद्द करें" + }, + "submission.general.info.pending-changes": { + "message": "बदलाव जो सहेजे नहीं गए" + }, + "submission.general.info.saved": { + "message": "सहेजा गया" + }, + "submission.general.save": { + "message": "सहेजें" + }, + "submission.general.save-later": { + "message": "बाद के लिए सहेजें" + }, + "submission.import-external.back-to-my-dspace": { + "message": "मेरे डीस्पेस पर वापस जाएं " + }, + "submission.import-external.page.hint": { + "message": "डीस्पेस में आयात करने के लिए वेब से आइटम खोजने के लिए ऊपर एक क्वेरी दर्ज करें।" + }, + "submission.import-external.page.title": { + "message": "बाहरी स्रोत से मेटाडेटा आयात करें" + }, + "submission.import-external.preview.button.import": { + "message": "प्रस्तुत करना प्रारंभ करें" + }, + "submission.import-external.preview.error.import.body": { + "message": "बाहरी स्रोत प्रविष्टि आयात प्रक्रिया के दौरान कोई त्रुटि उत्पन्न होती है।" + }, + "submission.import-external.preview.error.import.title": { + "message": "प्रस्तुत करने में त्रुटि" + }, + "submission.import-external.preview.subtitle": { + "message": "नीचे दिया गया मेटाडेटा बाहरी स्रोत से आयात किया गया था। जब आप प्रस्तुति शुरू करेंगे तो यह पहले से भर जाएगा।" + }, + "submission.import-external.preview.title": { + "message": "आइटम पूर्वावलोकन" + }, + "submission.import-external.preview.title.Journal": { + "message": "पत्रिका पूर्वावलोकन" + }, + "submission.import-external.preview.title.none": { + "message": "आइटम पूर्वावलोकन" + }, + "submission.import-external.preview.title.OrgUnit": { + "message": "संगठनात्मक इकाई पूर्वावलोकन" + }, + "submission.import-external.preview.title.Person": { + "message": "व्यक्ति पूर्वावलोकन" + }, + "submission.import-external.preview.title.Project": { + "message": "परियोजना पूर्वावलोकन" + }, + "submission.import-external.preview.title.Publication": { + "message": "प्रकाशन पूर्वावलोकन" + }, + "submission.import-external.search.button": { + "message": "खोजें" + }, + "submission.import-external.search.button.hint": { + "message": "खोजने के लिए कुछ शब्द लिखें" + }, + "submission.import-external.search.placeholder": { + "message": "बाहरी स्रोत खोजें" + }, + "submission.import-external.search.source.hint": { + "message": "बाहरी स्रोत चुनें" + }, + "submission.import-external.source.ads": { + "message": "NASA/ADS" + }, + "submission.import-external.source.arxiv": { + "message": "arXiv" + }, + "submission.import-external.source.cinii": { + "message": "CiNii" + }, + "submission.import-external.source.crossref": { + "message": "CrossRef" + }, + "submission.import-external.source.epo": { + "message": "यूरोपीय पेटेंट कार्यालय" + }, + "submission.import-external.source.lcname": { + "message": "लाइब्रेरी ऑफ़ कांग्रेस के नाम" + }, + "submission.import-external.source.loading": { + "message": "लोड हो रहा है..." + }, + "submission.import-external.source.openAIREFunding": { + "message": "OpenAIRE API का वित्तपोषण" + }, + "submission.import-external.source.orcid": { + "message": "ORCID" + }, + "submission.import-external.source.orcidWorks": { + "message": "ORCID" + }, + "submission.import-external.source.pubmed": { + "message": "पबमेड (Pubmed)" + }, + "submission.import-external.source.pubmedeu": { + "message": "पबमेड (Pubmed) यूरोप" + }, + "submission.import-external.source.scielo": { + "message": "SciELO" + }, + "submission.import-external.source.scopus": { + "message": "स्कोपस" + }, + "submission.import-external.source.sherpaJournal": { + "message": "शेरपा पत्रिकाएं" + }, + "submission.import-external.source.sherpaJournalIssn": { + "message": "ISSN द्वारा शेरपा पत्रिकाएं " + }, + "submission.import-external.source.sherpaPublisher": { + "message": "शेरपा प्रकाशक" + }, + "submission.import-external.source.vufind": { + "message": "VuFind" + }, + "submission.import-external.source.wos": { + "message": "वेब ऑफ़ साइंस" + }, + "submission.import-external.title": { + "message": "बाहरी स्रोत से मेटाडेटा आयात करें" + }, + "submission.import-external.title.Journal": { + "message": "किसी बाहरी स्रोत से पत्रिका आयात करें" + }, + "submission.import-external.title.JournalIssue": { + "message": "किसी बाहरी स्रोत से पत्रिका अंक आयात करें " + }, + "submission.import-external.title.JournalVolume": { + "message": "किसी बाहरी स्रोत से पत्रिका अंक आयात करें" + }, + "submission.import-external.title.none": { + "message": "बाहरी स्रोत से मेटाडेटा आयात करें" + }, + "submission.import-external.title.OrgUnit": { + "message": "किसी बाहरी स्रोत से प्रकाशक आयात करें" + }, + "submission.import-external.title.Person": { + "message": "किसी व्यक्ति को बाहरी स्रोत से आयात करें" + }, + "submission.import-external.title.Project": { + "message": "किसी बाहरी स्रोत से प्रोजेक्ट आयात करें" + }, + "submission.import-external.title.Publication": { + "message": "किसी बाहरी स्रोत से प्रकाशन आयात करें" + }, + "submission.sections.accesses.form.access-condition-hint": { + "message": "आइटम जमा करने के बाद उस पर लागू करने के लिए प्रयोग शर्त का चयन करें" + }, + "submission.sections.accesses.form.access-condition-label": { + "message": "पहुँच स्थिति प्रकार" + }, + "submission.sections.accesses.form.date-required": { + "message": "तिथि आवश्यक है।" + }, + "submission.sections.accesses.form.date-required-from": { + "message": "तिथि से अनुदान पहुंच आवश्यक है।" + }, + "submission.sections.accesses.form.date-required-until": { + "message": "तिथि तक पहुंच प्रदान करना आवश्यक है।" + }, + "submission.sections.accesses.form.discoverable-description": { + "message": "चयनित होने पर, यह आइटम खोज/ब्राउज़ में खोजने योग्य होगा। अचयनित होने पर, आइटम केवल सीधे लिंक के माध्यम से उपलब्ध होगा और कभी भी खोज/ब्राउज़ में दिखाई नहीं देगा। " + }, + "submission.sections.accesses.form.discoverable-label": { + "message": "खोज योग्य" + }, + "submission.sections.accesses.form.from-hint": { + "message": "उस तिथि का चयन करें जिससे संबंधित एक्सेस शर्त लागू की गई है" + }, + "submission.sections.accesses.form.from-label": { + "message": "अभिगमन आरम्भ तिथि" + }, + "submission.sections.accesses.form.from-placeholder": { + "message": "से" + }, + "submission.sections.accesses.form.group-label": { + "message": "समूह" + }, + "submission.sections.accesses.form.group-required": { + "message": "समूह की आवश्यकता है।" + }, + "submission.sections.accesses.form.until-hint": { + "message": "उस तिथि का चयन करें जब तक संबंधित पहुंच की शर्त लागू नहीं होती है" + }, + "submission.sections.accesses.form.until-label": { + "message": "तक पहुंच प्रदान करें" + }, + "submission.sections.accesses.form.until-placeholder": { + "message": "तक" + }, + "submission.sections.ccLicense.change": { + "message": "अपना लाइसेंस प्रकार बदलें…" + }, + "submission.sections.ccLicense.confirmation": { + "message": "मैं ऊपर लाइसेंस प्रदान करता हूं" + }, + "submission.sections.ccLicense.link": { + "message": "आपने निम्न लाइसेंस का चयन किया है:" + }, + "submission.sections.ccLicense.none": { + "message": "कोई लाइसेंस उपलब्ध नहीं" + }, + "submission.sections.ccLicense.option.select": { + "message": "कोई विकल्प चुनें…" + }, + "submission.sections.ccLicense.select": { + "message": "एक लाइसेंस प्रकार चुनें…" + }, + "submission.sections.ccLicense.type": { + "message": "अनुज्ञाप‍त्र के प्रकार " + }, + "submission.sections.describe.relationship-lookup.close": { + "message": "बंद करना" + }, + "submission.sections.describe.relationship-lookup.external-source.added": { + "message": "चयन में स्थानीय प्रविष्टि को सफलतापूर्वक जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Equipment": { + "message": "रिमोट उपकरण आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Event": { + "message": "दूरस्थ घटना आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Funding": { + "message": "सुदूर निधि आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.isAuthorOfPublication": { + "message": "दूरस्थ लेखक आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.isProjectOfPublication": { + "message": "परियोजना" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal": { + "message": "दूरस्थ पत्रिका आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Issue": { + "message": "दूरस्थ पत्रिका प्रकाशन आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": { + "message": "दूरस्थ जर्नल वॉल्यूम आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.none": { + "message": "दूरस्थ आइटम आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.OrgUnit": { + "message": "दूरस्थ संगठनात्मक इकाई आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Patent": { + "message": "रिमोट पेटेंट आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Person": { + "message": "दूरस्थ व्यक्ति आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Product": { + "message": "दूरस्थ उत्पाद आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Project": { + "message": "दूरस्थ परियोजना आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Publication": { + "message": "दूरस्थ प्रकाशन आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.authority": { + "message": "प्राधिकरण" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.authority.new": { + "message": "नई स्थानीय प्राधिकरण प्रविष्टि के रूप में आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.cancel": { + "message": "रद्द करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.collection": { + "message": "नई प्रविष्टियों को आयात करने के लिए संग्रह का चयन करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.entities": { + "message": "इकाइयां" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.entities.new": { + "message": "नई स्थानीय इकाई के रूप में आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.arxiv": { + "message": "arXiv से आयात किया जा रहा है" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.lcname": { + "message": "एलसी नाम से आयात करना" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.openAIREFunding": { + "message": "OpenAIRE API का वित्तपोषण" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.orcid": { + "message": "ORCID से आयात करना" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.pubmed": { + "message": "पबमेड से आयात करना" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaJournal": { + "message": "शेरपा पत्रिका से आयात" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaPublisher": { + "message": "शेरपा प्रकाशक से आयात करना" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.import": { + "message": "आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.added.local-entity": { + "message": "स्थानीय लेखक को चयन में सफलतापूर्वक जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.added.new-entity": { + "message": "चयन में बाहरी लेखक को सफलतापूर्वक आयात और जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.isAuthorOfPublication.title": { + "message": "दूरस्थ लेखक आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.isProjectOfPublication.added.new-entity": { + "message": "नई इकाई जोड़ी गई!" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.isProjectOfPublication.title": { + "message": "परियोजना" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.local-entity": { + "message": "चयन में स्थानीय पत्रिका अंक को सफलतापूर्वक जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.new-entity": { + "message": "चयन में बाहरी जर्नल अंक को सफलतापूर्वक आयात और जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.title": { + "message": "रिमोट जर्नल इश्यू आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.local-entity": { + "message": "स्थानीय पत्रिका अंक को चयन में सफलतापूर्वक जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.new-entity": { + "message": "चयन में बाहरी पत्रिका अंक को सफलतापूर्वक आयात कर जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.title": { + "message": "रिमोट जर्नल वॉल्यूम आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.local-entity": { + "message": "स्थानीय पत्रिका को चयन में सफलतापूर्वक जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.new-entity": { + "message": "चयन में बाहरी जर्नल को सफलतापूर्वक आयात और जोड़ा गया" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.title": { + "message": "दूरस्थ पत्रिका आयात करें" + }, + "submission.sections.describe.relationship-lookup.external-source.import-modal.select": { + "message": "एक स्थानीय मैच चुनें:" + }, + "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": { + "message": "एक नया नाम प्रकार सहेजें" + }, + "submission.sections.describe.relationship-lookup.name-variant.notification.content": { + "message": "क्या आप \"{{ value }}\" को इस व्यक्ति के लिए एक नाम प्रकार के रूप में सहेजना चाहते हैं ताकि आप और अन्य इसे भविष्य में प्रस्तुतीकरण के लिए पुन: उपयोग कर सकें? यदि आप नहीं करते हैं तो भी आप इस प्रस्तुतीकरण के लिए इसका उपयोग कर सकते हैं।" + }, + "submission.sections.describe.relationship-lookup.name-variant.notification.decline": { + "message": "इस प्रस्तुति के लिए ही प्रयोग करें" + }, + "submission.sections.describe.relationship-lookup.search-tab.deselect-all": { + "message": "सभी को अचिन्हिंत करें" + }, + "submission.sections.describe.relationship-lookup.search-tab.deselect-page": { + "message": "पृष्ठ का चयन रद्द करें" + }, + "submission.sections.describe.relationship-lookup.search-tab.loading": { + "message": "लोड हो रहा है..." + }, + "submission.sections.describe.relationship-lookup.search-tab.placeholder": { + "message": "खोज क्वेरी" + }, + "submission.sections.describe.relationship-lookup.search-tab.search": { + "message": "जाओ" + }, + "submission.sections.describe.relationship-lookup.search-tab.search-form.placeholder": { + "message": "खोज..." + }, + "submission.sections.describe.relationship-lookup.search-tab.select-all": { + "message": "सबका चयन करें" + }, + "submission.sections.describe.relationship-lookup.search-tab.select-page": { + "message": "पृष्ठ का चयन करें" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.arxiv": { + "message": "arXiv ({{ count }})" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.DataFile": { + "message": "({{ count }}) स्थानीय डेटा फ़ाइलें" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.DataPackage": { + "message": "({{ count }}) स्थानीय डेटा पैकेज" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isAuthorOfPublication": { + "message": "({{ count }}) स्थानीय लेखक" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isChildOrgUnitOf": { + "message": "संगठनात्मक इकाइयों के लिए खोजें" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfProject": { + "message": "परियोजना के निधिदाता" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingAgencyOfPublication": { + "message": "निधिदाता संस्थाओ के लिए खोजें" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isFundingOfPublication": { + "message": "अनुदान की खोज करें " + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalIssueOfPublication": { + "message": "({{ count }}) स्थानीय पत्रिका प्रकाशन" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalOfPublication": { + "message": "({{ count }}) स्थानीय पत्रिकाएं" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isJournalVolumeOfPublication": { + "message": "({{ count }}) स्थानीय पत्रिका खंड" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.isProjectOfPublication": { + "message": "परियोजनाएं" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal": { + "message": "({{ count }}) स्थानीय पत्रिकाएं" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.JournalIssue": { + "message": "({{ count }}) स्थानीय पत्रिका मुद्दे" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.JournalVolume": { + "message": "({{ count }}) स्थानीय पत्रिका खंड" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.lcname": { + "message": "({{ count }}) एलसी नाम" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.openAIREFunding": { + "message": "OpenAIRE API का वित्तपोषण" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.orcid": { + "message": "ORCID ({{ count }})" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.OrgUnit": { + "message": "({{ count }}) स्थानीय संगठनात्मक इकाइयाँ " + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.Person": { + "message": "({{ count }}) स्थानीय लेखक" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.Project": { + "message": "({{ count }}) स्थानीय परियोजनाएं" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.Publication": { + "message": "({{ count }}) स्थानीय प्रकाशन" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.pubmed": { + "message": "({{ count }}) पबमेड (Pubmed)" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaJournal": { + "message": "({{ count }}) शेरपा पत्रिका" + }, + "submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaPublisher": { + "message": "({{ count }}) शेरपा प्रकाशक" + }, + "submission.sections.describe.relationship-lookup.search-tab.toggle-dropdown": { + "message": "ड्रॉपडाउन टॉगल करें" + }, + "submission.sections.describe.relationship-lookup.selected": { + "message": "चयनित {{ size }} आइटम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.no-selection": { + "message": "आपका चयन वर्तमान में खाली है।" + }, + "submission.sections.describe.relationship-lookup.selection-tab.search-form.placeholder": { + "message": "खोज..." + }, + "submission.sections.describe.relationship-lookup.selection-tab.settings": { + "message": "समायोजन" + }, + "submission.sections.describe.relationship-lookup.selection-tab.tab-title": { + "message": "वर्तमान चयन ({{ count }})" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.arxiv": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.crossref": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.DataFile": { + "message": "चयनित डेटा फ़ाइलें" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.DataPackage": { + "message": "चयनित डेटा पैकेज" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.epo": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.isAuthorOfPublication": { + "message": "चयनित लेखक" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.isChildOrgUnitOf": { + "message": "चयनित संगठनात्मक इकाई" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.isFundingAgencyOfPublication": { + "message": "चयनित फंडिंग एजेंसी" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.isFundingOfPublication": { + "message": "चयनित अनुदान" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalIssueOfPublication": { + "message": "चयनित अंक" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalOfPublication": { + "message": "चयनित पत्रिकाएं" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.isJournalVolumeOfPublication": { + "message": "चयनित पत्रिका खंड" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.isProjectOfPublication": { + "message": "परियोजना" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.Journal": { + "message": "चयनित पत्रिकाएं" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.JournalIssue": { + "message": "चयनित अंक" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.JournalVolume": { + "message": "चयनित पत्रिका खंड" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.lcname": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.openAIREFunding": { + "message": "OpenAIRE API का वित्तपोषण" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.orcid": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.orcidv2": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.OrgUnit": { + "message": "चयनित संगठनात्मक इकाइयाँ" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.Person": { + "message": "चयनित लेखक" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.Project": { + "message": "चयनित परियोजनाएं" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.Publication": { + "message": "चयनित प्रकाशन" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.pubmed": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.scielo": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.scopus": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaJournal": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.sherpaPublisher": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.selection-tab.title.wos": { + "message": "खोज के परिणाम" + }, + "submission.sections.describe.relationship-lookup.title.DataFile": { + "message": "डेटा फ़ाइलें" + }, + "submission.sections.describe.relationship-lookup.title.DataPackage": { + "message": "डेटा पैकेज" + }, + "submission.sections.describe.relationship-lookup.title.Funding Agency": { + "message": "निधिकरण संस्था" + }, + "submission.sections.describe.relationship-lookup.title.isAuthorOfPublication": { + "message": "लेखक" + }, + "submission.sections.describe.relationship-lookup.title.isChildOrgUnitOf": { + "message": "जनक संगठनात्मक इकाई" + }, + "submission.sections.describe.relationship-lookup.title.isFundingAgencyOfProject": { + "message": "परियोजना के निधिदाता" + }, + "submission.sections.describe.relationship-lookup.title.isFundingAgencyOfPublication": { + "message": "निधिकरण संस्था" + }, + "submission.sections.describe.relationship-lookup.title.isFundingOfPublication": { + "message": "निधिकरण" + }, + "submission.sections.describe.relationship-lookup.title.isJournalIssueOfPublication": { + "message": "पत्रिका के मुद्दे" + }, + "submission.sections.describe.relationship-lookup.title.isJournalOfPublication": { + "message": "पत्रिकाएं" + }, + "submission.sections.describe.relationship-lookup.title.isJournalVolumeOfPublication": { + "message": "पत्रिका खंड" + }, + "submission.sections.describe.relationship-lookup.title.isProjectOfPublication": { + "message": "परियोजनाएं" + }, + "submission.sections.describe.relationship-lookup.title.JournalIssue": { + "message": "पत्रिका प्रकाशन" + }, + "submission.sections.describe.relationship-lookup.title.JournalVolume": { + "message": "पत्रिका खंड" + }, + "submission.sections.describe.relationship-lookup.title.OrgUnit": { + "message": "संगठनात्मक इकाइयाँ" + }, + "submission.sections.describe.relationship-lookup.title.Person": { + "message": "लेखक" + }, + "submission.sections.describe.relationship-lookup.title.Project": { + "message": "परियोजनाएं" + }, + "submission.sections.describe.relationship-lookup.title.Publication": { + "message": "प्रकाशन" + }, + "submission.sections.general.add-more": { + "message": "और जोड़ें" + }, + "submission.sections.general.cannot_deposit": { + "message": "फ़ॉर्म में त्रुटियों के कारण जमा पूरा नहीं किया जा सकता है।
कृपया जमा को पूरा करने के लिए सभी आवश्यक फ़ील्ड भरें।" + }, + "submission.sections.general.collection": { + "message": "संग्रह" + }, + "submission.sections.general.deposit_error_notice": { + "message": "आइटम प्रस्तुत करते समय एक समस्या हुई थी, कृपया बाद में फिर से प्रयास करें।" + }, + "submission.sections.general.deposit_success_notice": { + "message": "प्रस्तुति को सफलतापूर्वक जमा किया गया।" + }, + "submission.sections.general.discard_error_notice": { + "message": "आइटम को हटाते समय एक समस्या हुई थी, कृपया बाद में फिर से प्रयास करें।" + }, + "submission.sections.general.discard_success_notice": { + "message": "प्रस्तुति सफलतापूर्वक रद्द करी गयी। " + }, + "submission.sections.general.metadata-extracted": { + "message": "नया मेटाडेटा निकाला गया है और {{sectionId}} अनुभाग में जोड़ा गया है।" + }, + "submission.sections.general.metadata-extracted-new-section": { + "message": "सबमिशन में नया {{sectionId}} अनुभाग जोड़ा गया है।" + }, + "submission.sections.general.no-collection": { + "message": "कोई संग्रह नहीं मिला" + }, + "submission.sections.general.no-sections": { + "message": "कोई विकल्प उपलब्ध नहीं" + }, + "submission.sections.general.save_error_notice": { + "message": "आइटम सहेजते समय एक समस्या हुई थी, कृपया बाद में पुन: प्रयास करें।" + }, + "submission.sections.general.save_success_notice": { + "message": "प्रस्तुतीकरण सफलतापूर्वक सहेजा गया।" + }, + "submission.sections.general.search-collection": { + "message": "संग्रह के लिए खोजें" + }, + "submission.sections.general.sections_not_valid": { + "message": "अपूर्ण खंड हैं।" + }, + "submission.sections.license.granted-label": { + "message": "मैं उपरोक्त लाइसेंस की पुष्टि करता हूं" + }, + "submission.sections.license.notgranted": { + "message": "आपको अनुज्ञापत्र स्वीकार करना होगा" + }, + "submission.sections.license.required": { + "message": "आपको लाइसेंस स्वीकार करना होगा" + }, + "submission.sections.sherpa-policy.title-empty": { + "message": "प्रकाशक नीति की कोई जानकारी उपलब्ध नहीं है। अगर आपके काम में संबधित आईएसएसएन है, तो कृपया संबंधित प्रकाशक की खुली पहुंच (ओपन एक्सेस) नीतियों को देखने के लिए इसे ऊपर दर्ज करें।" + }, + "submission.sections.sherpa.error.message": { + "message": "शेरपा जानकारी प्राप्त करने में त्रुटि हुई थी" + }, + "submission.sections.sherpa.publication.information": { + "message": "प्रकाशन की जानकारी" + }, + "submission.sections.sherpa.publication.information.issns": { + "message": "ISSNs" + }, + "submission.sections.sherpa.publication.information.publishers": { + "message": "प्रकाशक" + }, + "submission.sections.sherpa.publication.information.romeoPub": { + "message": "रोमियो पब" + }, + "submission.sections.sherpa.publication.information.title": { + "message": "शीर्षक" + }, + "submission.sections.sherpa.publication.information.url": { + "message": "यूआरएल (URL)" + }, + "submission.sections.sherpa.publication.information.zetoPub": { + "message": "ज़ेटो पब (Zeto Pub)" + }, + "submission.sections.sherpa.publisher.policy": { + "message": "प्रकाशक नीति" + }, + "submission.sections.sherpa.publisher.policy.conditions": { + "message": "स्थितियाँ" + }, + "submission.sections.sherpa.publisher.policy.description": { + "message": "नीचे दी गई जानकारी शेरपा रोमियो के माध्यम से मिली। आपके प्रकाशक की नीतियों के आधार पर, यह इस बारे में सलाह देता है कि क्या प्रतिबंध आवश्यक हो सकता है और/या आपको कौन सी फाइलें अपलोड करने की अनुमति है। यदि आपके कोई प्रश्न हैं, तो कृपया पाद लेख में फ़ीडबैक फ़ॉर्म के माध्यम से अपने साइट व्यवस्थापक से संपर्क करें।" + }, + "submission.sections.sherpa.publisher.policy.embargo": { + "message": "प्रतिबंध" + }, + "submission.sections.sherpa.publisher.policy.license": { + "message": "अनुज्ञाप‍त्र" + }, + "submission.sections.sherpa.publisher.policy.location": { + "message": "स्थान" + }, + "submission.sections.sherpa.publisher.policy.more.information": { + "message": "अधिक जानकारी के लिए, कृपया निम्नलिखित लिंक देखें:" + }, + "submission.sections.sherpa.publisher.policy.noembargo": { + "message": "कोई प्रतिबंध नहीं" + }, + "submission.sections.sherpa.publisher.policy.nolocation": { + "message": "कोई भी नहीं" + }, + "submission.sections.sherpa.publisher.policy.openaccess": { + "message": "इस पत्रिका की नीति द्वारा अनुमत ओपन एक्सेस पाथवे लेख संस्करण द्वारा नीचे सूचीबद्ध हैं। अधिक जानकारी के लिए पथ पर क्लिक करें" + }, + "submission.sections.sherpa.publisher.policy.prerequisites": { + "message": "पूर्वापेक्षाएँ" + }, + "submission.sections.sherpa.publisher.policy.refresh": { + "message": "ताज़ा करें" + }, + "submission.sections.sherpa.publisher.policy.version": { + "message": "संस्करण" + }, + "submission.sections.sherpa.record.information": { + "message": "दस्तावेज की जानकारी" + }, + "submission.sections.sherpa.record.information.date.created": { + "message": "बनाने की तिथि" + }, + "submission.sections.sherpa.record.information.date.modified": { + "message": "अंतिम बार संशोधित" + }, + "submission.sections.sherpa.record.information.id": { + "message": "पहचान" + }, + "submission.sections.sherpa.record.information.uri": { + "message": "यूआरआई (URI)" + }, + "submission.sections.status.errors.aria": { + "message": "इसमें त्रुटियां हैं" + }, + "submission.sections.status.errors.title": { + "message": "त्रुटियाँ" + }, + "submission.sections.status.info.aria": { + "message": "अतिरिक्त जानकारी" + }, + "submission.sections.status.info.title": { + "message": "अतिरिक्त जानकारी" + }, + "submission.sections.status.valid.aria": { + "message": "यह सही है" + }, + "submission.sections.status.valid.title": { + "message": "वैध" + }, + "submission.sections.status.warnings.aria": { + "message": "चेतावनियाँ हैं" + }, + "submission.sections.status.warnings.title": { + "message": "चेतावनी" + }, + "submission.sections.submit.progressbar.accessCondition": { + "message": "आइटम पहुंच की शर्तें" + }, + "submission.sections.submit.progressbar.CClicense": { + "message": "क्रिएटिव कामन्स लाइसेंस" + }, + "submission.sections.submit.progressbar.describe.recycle": { + "message": "पुनर्चक्रण" + }, + "submission.sections.submit.progressbar.describe.stepcustom": { + "message": "वर्णन करें" + }, + "submission.sections.submit.progressbar.describe.stepone": { + "message": "वर्णन करना" + }, + "submission.sections.submit.progressbar.describe.steptwo": { + "message": "वर्णन करें" + }, + "submission.sections.submit.progressbar.detect-duplicate": { + "message": "संभावित दोहराव" + }, + "submission.sections.submit.progressbar.license": { + "message": "जमा करने के लिए अनुज्ञापत्र " + }, + "submission.sections.submit.progressbar.sherpaPolicies": { + "message": "प्रकाशक खुली पहुँच नीति की जानकारी" + }, + "submission.sections.submit.progressbar.sherpapolicy": { + "message": "शेरपा नीतियां" + }, + "submission.sections.submit.progressbar.upload": { + "message": "फाइलें अपलोड करें" + }, + "submission.sections.toggle.aria.close": { + "message": "{{sectionHeader}} सेक्शन को छोटा करें" + }, + "submission.sections.toggle.aria.open": { + "message": "{{sectionHeader}} सेक्शन को विस्तृत करें" + }, + "submission.sections.toggle.close": { + "message": "खंड बंद करें" + }, + "submission.sections.toggle.open": { + "message": "खुला खंड" + }, + "submission.sections.upload.delete.confirm.cancel": { + "message": "रद्द करें" + }, + "submission.sections.upload.delete.confirm.info": { + "message": "यह कार्रवाई पूर्ववत नहीं की जा सकती। क्या आपको यकीन है?" + }, + "submission.sections.upload.delete.confirm.submit": { + "message": "हां मुझे यकीन है" + }, + "submission.sections.upload.delete.confirm.title": { + "message": "बिटस्ट्रीम हटाएं" + }, + "submission.sections.upload.delete.submit": { + "message": "हटाएं" + }, + "submission.sections.upload.download.title": { + "message": "बिटस्ट्रीम डाउनलोड करें" + }, + "submission.sections.upload.drop-message": { + "message": "आइटम के साथ संलग्न करने के लिए फ़ाइलें छोड़ें" + }, + "submission.sections.upload.edit.title": { + "message": "बिटस्ट्रीम संपादित करें" + }, + "submission.sections.upload.form.access-condition-hint": { + "message": "आइटम जमा होने के बाद बिटस्ट्रीम पर लागू करने के लिए एक एक्सेस शर्त का चयन करें" + }, + "submission.sections.upload.form.access-condition-label": { + "message": "पहुँच स्थिति प्रकार" + }, + "submission.sections.upload.form.date-required": { + "message": "तिथि आवश्यक है।" + }, + "submission.sections.upload.form.date-required-from": { + "message": "अभिगमन आरम्भ तिथि आवश्यक है।" + }, + "submission.sections.upload.form.date-required-until": { + "message": "तिथि तक प्रवेश प्रदान करना आवश्यक है।" + }, + "submission.sections.upload.form.from-hint": { + "message": "उस तिथि का चयन करें जिससे संबंधित पहुंच शर्त लागू करि जाएगी" + }, + "submission.sections.upload.form.from-label": { + "message": "से पहुंच प्रदान करें" + }, + "submission.sections.upload.form.from-placeholder": { + "message": "से" + }, + "submission.sections.upload.form.group-label": { + "message": "समूह" + }, + "submission.sections.upload.form.group-required": { + "message": "समूह की आवश्यकता है।" + }, + "submission.sections.upload.form.until-hint": { + "message": "उस तिथि का चयन करें जब तक संबंधित पहुंच शर्त लागू नहीं हो जाती" + }, + "submission.sections.upload.form.until-label": { + "message": "अभिगमन अंत तिथि " + }, + "submission.sections.upload.form.until-placeholder": { + "message": "तक" + }, + "submission.sections.upload.header.policy.default.nolist": { + "message": "{{CollectionName}} संग्रह में अपलोड की गई फ़ाइलें निम्न समूह (समूहों) के अनुसार पहुंच योग्य होंगी:" + }, + "submission.sections.upload.header.policy.default.withlist": { + "message": "कृपया ध्यान दें कि {{collectionName}} संग्रह में अपलोड की गई फ़ाइलें निम्न समूह (समूहों) के साथ एकल फ़ाइल के लिए स्पष्ट रूप से तय की गई फ़ाइलों के अतिरिक्त पहुंच योग्य होंगी:" + }, + "submission.sections.upload.info": { + "message": "यहां आपको आइटम में वर्तमान में सभी फाइलें मिलेंगी। आप फ़ाइल मेटाडेटा और एक्सेस शर्तों को अपडेट कर सकते हैं या अतिरिक्त फ़ाइलें अपलोड कर सकते हैं बस उन्हें पृष्ठ में हर जगह खींच कर छोड़ सकते हैं" + }, + "submission.sections.upload.no-entry": { + "message": "नहीं" + }, + "submission.sections.upload.no-file-uploaded": { + "message": "अभी तक कोई फ़ाइल अपलोड नहीं हुई है|" + }, + "submission.sections.upload.save-metadata": { + "message": "मेटाडेटा सहेजें" + }, + "submission.sections.upload.undo": { + "message": "रद्द करें" + }, + "submission.sections.upload.upload-failed": { + "message": "अपलोड विफल" + }, + "submission.sections.upload.upload-successful": { + "message": "अपलोड सफल" + }, + "submission.submit.breadcrumbs": { + "message": "नया प्रस्तुतीकरण" + }, + "submission.submit.title": { + "message": "नया प्रस्तुतीकरण" + }, + "submission.workflow.generic.delete": { + "message": "हटाएं" + }, + "submission.workflow.generic.delete-help": { + "message": "यदि आप इस आइटम को त्यागना चाहते हैं, तो \"हटाएं\" चुनें। फिर आपको इसकी पुष्टि करने के लिए कहा जाएगा।" + }, + "submission.workflow.generic.edit": { + "message": "संपादित करें" + }, + "submission.workflow.generic.edit-help": { + "message": "आइटम का मेटाडेटा बदलने के लिए इस विकल्प का चयन करें।" + }, + "submission.workflow.generic.view": { + "message": "देखें" + }, + "submission.workflow.generic.view-help": { + "message": "आइटम का मेटाडेटा देखने के लिए इस विकल्प का चयन करें।" + }, + "submission.workflow.tasks.claimed.approve": { + "message": "स्वीकृत करें" + }, + "submission.workflow.tasks.claimed.approve_help": { + "message": "यदि आपने आइटम की समीक्षा की है और यह संग्रह में शामिल करने के लिए उपयुक्त है, तो \"स्वीकृत करें\" चुनें।" + }, + "submission.workflow.tasks.claimed.edit": { + "message": "संपादित करें" + }, + "submission.workflow.tasks.claimed.edit_help": { + "message": "आइटम का मेटाडेटा बदलने के लिए इस विकल्प का चयन करें।" + }, + "submission.workflow.tasks.claimed.reject_help": { + "message": "यदि आपने आइटम की समीक्षा की है और पाया है कि यह संग्रह में शामिल करने के लिए उपयुक्त नहीं है, तो \"अस्वीकार करें\" चुनें। फिर आपको एक संदेश दर्ज करने के लिए कहा जाएगा जो यह दर्शाता है कि आइटम अनुपयुक्त क्यों है, और क्या जमाकर्ता को कुछ बदलना चाहिए और फिर से सबमिट करना चाहिए।" + }, + "submission.workflow.tasks.claimed.reject.reason.info": { + "message": "कृपया नीचे दिए गए बॉक्स में प्रस्तुति को अस्वीकार करने का अपना कारण दर्ज करें, यह इंगित करते हुए कि क्या प्रस्तुतकर्ता किसी समस्या को ठीक कर सकता है और फिर से प्रस्तुत कर सकता है। " + }, + "submission.workflow.tasks.claimed.reject.reason.placeholder": { + "message": "अस्वीकार करने का कारण बताएं" + }, + "submission.workflow.tasks.claimed.reject.reason.submit": { + "message": "आइटम अस्वीकार करें" + }, + "submission.workflow.tasks.claimed.reject.reason.title": { + "message": "कारण" + }, + "submission.workflow.tasks.claimed.reject.submit": { + "message": "अस्वीकार करें" + }, + "submission.workflow.tasks.claimed.return": { + "message": "पूल में वापस करें " + }, + "submission.workflow.tasks.claimed.return_help": { + "message": "कार्य को पूल में लौटाएं ताकि कोई अन्य उपयोगकर्ता कार्य कर सके।" + }, + "submission.workflow.tasks.generic.error": { + "message": "ऑपरेशन के दौरान हुई गड़बड़ी..." + }, + "submission.workflow.tasks.generic.processing": { + "message": "संसाधित किया जा रहा है..." + }, + "submission.workflow.tasks.generic.submitter": { + "message": "प्रस्तुतकर्ता" + }, + "submission.workflow.tasks.generic.success": { + "message": "संचालन सफल रहा" + }, + "submission.workflow.tasks.pool.claim": { + "message": "दावा करें" + }, + "submission.workflow.tasks.pool.claim_help": { + "message": "यह कार्य स्वयं को सौंपें।" + }, + "submission.workflow.tasks.pool.hide-detail": { + "message": "विवरण छुपाएं" + }, + "submission.workflow.tasks.pool.show-detail": { + "message": "विवरण दिखाएँ" + }, + "submission.workspace.generic.view": { + "message": "देखें" + }, + "submission.workspace.generic.view-help": { + "message": "आइटम का मेटाडेटा देखने के लिए इस विकल्प का चयन करें।" + }, + "thumbnail.default.alt": { + "message": "थंबनेल चित्र" + }, + "thumbnail.default.placeholder": { + "message": "कोई थंबनेल उपलब्ध नहीं" + }, + "thumbnail.orgunit.alt": { + "message": "संगठन इकाई चिन्ह" + }, + "thumbnail.orgunit.placeholder": { + "message": "संगठन इकाई स्थानधारक छवि" + }, + "thumbnail.person.alt": { + "message": "प्रोफ़ाइल चित्र" + }, + "thumbnail.person.placeholder": { + "message": "कोई प्रोफ़ाइल चित्र उपलब्ध नहीं है" + }, + "thumbnail.project.alt": { + "message": "परियोजना चिन्ह " + }, + "thumbnail.project.placeholder": { + "message": "परियोजना स्थानधारक छवि" + }, + "title": { + "message": "डीस्पेस" + }, + "uploader.browse": { + "message": "ब्राउज़ करें" + }, + "uploader.delete.btn-title": { + "message": "हटाएं" + }, + "uploader.drag-message": { + "message": "अपनी फ़ाइलों को यहाँ खींचें और छोड़ें" + }, + "uploader.or": { + "message": ", अथवा" + }, + "uploader.processing": { + "message": "प्रसंस्करण" + }, + "uploader.queue-length": { + "message": "कतार की लंबाई" + }, + "virtual-metadata.delete-item.info": { + "message": "उन प्रकारों का चयन करें जिनके लिए आप वर्चुअल मेटाडेटा को वास्तविक मेटाडेटा के रूप में सहेजना चाहते हैं" + }, + "virtual-metadata.delete-item.modal-head": { + "message": "इस संबंध का आभासी मेटाडेटा" + }, + "virtual-metadata.delete-relationship.modal-head": { + "message": "वे आइटम चुनें जिनके लिए आप आभासी मेटाडेटा को वास्तविक मेटाडेटा के रूप में सहेजना चाहते हैं" + }, + "vocabulary-treeview.header": { + "message": "श्रेणीबद्ध वृक्ष दृश्य" + }, + "vocabulary-treeview.load-more": { + "message": "और लोड करें" + }, + "vocabulary-treeview.search.form.reset": { + "message": "रीसेट" + }, + "vocabulary-treeview.search.form.search": { + "message": "खोज" + }, + "vocabulary-treeview.search.no-result": { + "message": "दिखाने के लिए कोई आइटम नहीं थे" + }, + "vocabulary-treeview.tree.description.nsi": { + "message": "नॉर्वेजियन साइंस इंडेक्स" + }, + "vocabulary-treeview.tree.description.srsc": { + "message": "अनुसंधान विषय श्रेणियाँ" + }, + "workflow-item.delete.button.cancel": { + "message": "रद्द करें" + }, + "workflow-item.delete.button.confirm": { + "message": "हटाएं" + }, + "workflow-item.delete.header": { + "message": "कार्यप्रवाह आइटम हटाएं" + }, + "workflow-item.delete.notification.error.content": { + "message": "कार्यप्रवाह आइटम हटाया नहीं जा सका" + }, + "workflow-item.delete.notification.error.title": { + "message": "कुछ गलत हो गया" + }, + "workflow-item.delete.notification.success.content": { + "message": "यह कार्यप्रवाह आइटम सफलतापूर्वक हटा दिया गया था" + }, + "workflow-item.delete.notification.success.title": { + "message": "हटाए गए" + }, + "workflow-item.delete.title": { + "message": "कार्यप्रवाह आइटम हटाएं" + }, + "workflow-item.edit.breadcrumbs": { + "message": "कार्यप्रवाह वस्तु संपादित करें" + }, + "workflow-item.edit.title": { + "message": "कार्यप्रवाह आइटम संपादित करें" + }, + "workflow-item.send-back.button.cancel": { + "message": "रद्द करें" + }, + "workflow-item.send-back.button.confirm": { + "message": "वापस भेजे" + }, + "workflow-item.send-back.header": { + "message": "कार्यप्रवाह आइटम को वापस प्रस्तुतकर्ता को भेजें" + }, + "workflow-item.send-back.notification.error.content": { + "message": "कार्यप्रवाह आइटम को सबमिटर को वापस नहीं भेजा जा सका" + }, + "workflow-item.send-back.notification.error.title": { + "message": "कुछ गलत हो गया" + }, + "workflow-item.send-back.notification.success.content": { + "message": "यह कार्यप्रवाह आइटम सफलतापूर्वक सबमिट करने वाले को वापस भेज दिया गया था" + }, + "workflow-item.send-back.notification.success.title": { + "message": "प्रस्तुतकर्ता को वापस भेजा गया" + }, + "workflow-item.send-back.title": { + "message": "कार्यप्रवाह आइटम को वापस प्रस्तुतिकर्ता को भेजें" + }, + "workflow-item.view.breadcrumbs": { + "message": "कार्यप्रवाह दृश्य" + }, + "workflow.search.results.head": { + "message": "कार्यप्रवाह कार्य" + }, + "workflowAdmin.search.results.head": { + "message": "कार्यप्रवाह व्यवस्थापित करें" + }, + "workspace-item.view.breadcrumbs": { + "message": "कार्यक्षेत्र दृश्य" + }, + "workspace-item.view.title": { + "message": "कार्यक्षेत्र दृश्य" + }, + "workspace.search.results.head": { + "message": "आपकी प्रस्तुतियाँ" + } +} \ No newline at end of file From dd2317699acb7ec50db084647e3c5b13c3ff94d2 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 19 Sep 2022 10:11:40 +0200 Subject: [PATCH 21/97] make search-settings.component themed --- .../themed-search-settings.component.ts | 33 +++++++++++++++++++ src/app/shared/search/search.module.ts | 2 ++ .../search-settings.component.html | 0 .../search-settings.component.scss | 0 .../search-settings.component.ts | 31 +++++++++++++++++ src/themes/custom/theme.module.ts | 4 ++- 6 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/app/shared/search/search-settings/themed-search-settings.component.ts create mode 100644 src/themes/custom/app/shared/search-settings/search-settings.component.html create mode 100644 src/themes/custom/app/shared/search-settings/search-settings.component.scss create mode 100644 src/themes/custom/app/shared/search-settings/search-settings.component.ts diff --git a/src/app/shared/search/search-settings/themed-search-settings.component.ts b/src/app/shared/search/search-settings/themed-search-settings.component.ts new file mode 100644 index 0000000000..b1f1d08264 --- /dev/null +++ b/src/app/shared/search/search-settings/themed-search-settings.component.ts @@ -0,0 +1,33 @@ +import { Component, Input } from '@angular/core'; +import { ThemedComponent } from '../../theme-support/themed.component'; +import { SearchSettingsComponent } from './search-settings.component'; +import { SortOptions } from '../../../core/cache/models/sort-options.model'; + +/** + * Themed wrapper for SearchSettingsComponent + */ +@Component({ + selector: 'ds-themed-search-settings', + styleUrls: [], + templateUrl: '../../theme-support/themed.component.html', +}) +export class ThemedSearchSettingsComponent extends ThemedComponent { + @Input() currentSortOption: SortOptions; + @Input() sortOptionsList: SortOptions[]; + + + protected inAndOutputNames: (keyof SearchSettingsComponent & keyof this)[] = [ + 'currentSortOption', 'sortOptionsList']; + + protected getComponentName(): string { + return 'SearchSettingsComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../../themes/${themeName}/app/shared/search/search-settings/search-settings.component`); + } + + protected importUnthemedComponent(): Promise { + return import('./search-settings.component'); + } +} diff --git a/src/app/shared/search/search.module.ts b/src/app/shared/search/search.module.ts index 668d260c23..51ba17c6cf 100644 --- a/src/app/shared/search/search.module.ts +++ b/src/app/shared/search/search.module.ts @@ -28,12 +28,14 @@ import { MissingTranslationHelper } from '../translate/missing-translation.helpe import { SharedModule } from '../shared.module'; import { SearchResultsComponent } from './search-results/search-results.component'; import { SearchComponent } from './search.component'; +import { ThemedSearchSettingsComponent } from './search-settings/themed-search-settings.component'; const COMPONENTS = [ SearchComponent, SearchResultsComponent, SearchSidebarComponent, SearchSettingsComponent, + ThemedSearchSettingsComponent, SearchFiltersComponent, SearchFilterComponent, SearchFacetFilterComponent, diff --git a/src/themes/custom/app/shared/search-settings/search-settings.component.html b/src/themes/custom/app/shared/search-settings/search-settings.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/shared/search-settings/search-settings.component.scss b/src/themes/custom/app/shared/search-settings/search-settings.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/shared/search-settings/search-settings.component.ts b/src/themes/custom/app/shared/search-settings/search-settings.component.ts new file mode 100644 index 0000000000..db27ac95f4 --- /dev/null +++ b/src/themes/custom/app/shared/search-settings/search-settings.component.ts @@ -0,0 +1,31 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE_ATMIRE and NOTICE_ATMIRE files at the root of the source + * tree and available online at + * + * https://www.atmire.com/software-license/ + */ +import { Component } from '@angular/core'; +import { + SearchSettingsComponent as BaseComponent, +} from '../../../../../app/shared/search/search-settings/search-settings.component'; +import { SEARCH_CONFIG_SERVICE } from '../../../../../app/my-dspace-page/my-dspace-page.component'; +import { SearchConfigurationService } from '../../../../../app/core/shared/search/search-configuration.service'; + + +@Component({ + selector: 'ds-search-settings', + // styleUrls: ['./search-settings.component.scss'], + styleUrls: ['../../../../../app/shared/search/search-settings/search-settings.component.scss'], + // templateUrl: './search-settings.component.html', + templateUrl: '../../../../../app/shared/search/search-settings/search-settings.component.html', + providers: [ + { + provide: SEARCH_CONFIG_SERVICE, + useClass: SearchConfigurationService + } + ] + +}) + +export class SearchSettingsComponent extends BaseComponent {} diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index e2e97b9087..3457259792 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -84,6 +84,7 @@ import { SearchModule } from '../../app/shared/search/search.module'; import { ResourcePoliciesModule } from '../../app/shared/resource-policies/resource-policies.module'; import { ComcolModule } from '../../app/shared/comcol/comcol.module'; import { FeedbackComponent } from './app/info/feedback/feedback.component'; +import { SearchSettingsComponent } from './app/shared/search-settings/search-settings.component'; const DECLARATIONS = [ FileSectionComponent, @@ -126,7 +127,8 @@ const DECLARATIONS = [ NavbarComponent, HeaderNavbarWrapperComponent, BreadcrumbsComponent, - FeedbackComponent + FeedbackComponent, + SearchSettingsComponent ]; @NgModule({ From a17ee028dfebdcce95f115a275d3b906215ee5e3 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 19 Sep 2022 11:56:04 +0200 Subject: [PATCH 22/97] make search-settings.component themed --- .../shared/search/search-sidebar/search-sidebar.component.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/shared/search/search-sidebar/search-sidebar.component.html b/src/app/shared/search/search-sidebar/search-sidebar.component.html index e17fe941ba..863bd2d71f 100644 --- a/src/app/shared/search/search-sidebar/search-sidebar.component.html +++ b/src/app/shared/search/search-sidebar/search-sidebar.component.html @@ -21,7 +21,8 @@ [currentConfiguration]="configuration" [refreshFilters]="refreshFilters" [inPlaceSearch]="inPlaceSearch"> - + From f84e4d6146c000ffe8da36f0541ffd6347af0e97 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 19 Sep 2022 12:35:21 +0200 Subject: [PATCH 23/97] 89685: Resolve wrong directory --- .../search-settings/search-settings.component.html | 0 .../search-settings/search-settings.component.scss | 0 .../search-settings/search-settings.component.ts | 10 +++++----- src/themes/custom/lazy-theme.module.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename src/themes/custom/app/shared/{ => search}/search-settings/search-settings.component.html (100%) rename src/themes/custom/app/shared/{ => search}/search-settings/search-settings.component.scss (100%) rename src/themes/custom/app/shared/{ => search}/search-settings/search-settings.component.ts (56%) diff --git a/src/themes/custom/app/shared/search-settings/search-settings.component.html b/src/themes/custom/app/shared/search/search-settings/search-settings.component.html similarity index 100% rename from src/themes/custom/app/shared/search-settings/search-settings.component.html rename to src/themes/custom/app/shared/search/search-settings/search-settings.component.html diff --git a/src/themes/custom/app/shared/search-settings/search-settings.component.scss b/src/themes/custom/app/shared/search/search-settings/search-settings.component.scss similarity index 100% rename from src/themes/custom/app/shared/search-settings/search-settings.component.scss rename to src/themes/custom/app/shared/search/search-settings/search-settings.component.scss diff --git a/src/themes/custom/app/shared/search-settings/search-settings.component.ts b/src/themes/custom/app/shared/search/search-settings/search-settings.component.ts similarity index 56% rename from src/themes/custom/app/shared/search-settings/search-settings.component.ts rename to src/themes/custom/app/shared/search/search-settings/search-settings.component.ts index db27ac95f4..e17c2425b5 100644 --- a/src/themes/custom/app/shared/search-settings/search-settings.component.ts +++ b/src/themes/custom/app/shared/search/search-settings/search-settings.component.ts @@ -8,17 +8,17 @@ import { Component } from '@angular/core'; import { SearchSettingsComponent as BaseComponent, -} from '../../../../../app/shared/search/search-settings/search-settings.component'; -import { SEARCH_CONFIG_SERVICE } from '../../../../../app/my-dspace-page/my-dspace-page.component'; -import { SearchConfigurationService } from '../../../../../app/core/shared/search/search-configuration.service'; +} from '../../../../../../app/shared/search/search-settings/search-settings.component'; +import { SEARCH_CONFIG_SERVICE } from '../../../../../../app/my-dspace-page/my-dspace-page.component'; +import { SearchConfigurationService } from '../../../../../../app/core/shared/search/search-configuration.service'; @Component({ selector: 'ds-search-settings', // styleUrls: ['./search-settings.component.scss'], - styleUrls: ['../../../../../app/shared/search/search-settings/search-settings.component.scss'], + styleUrls: ['../../../../../../app/shared/search/search-settings/search-settings.component.scss'], // templateUrl: './search-settings.component.html', - templateUrl: '../../../../../app/shared/search/search-settings/search-settings.component.html', + templateUrl: '../../../../../../app/shared/search/search-settings/search-settings.component.html', providers: [ { provide: SEARCH_CONFIG_SERVICE, diff --git a/src/themes/custom/lazy-theme.module.ts b/src/themes/custom/lazy-theme.module.ts index 7015270363..c25460b576 100644 --- a/src/themes/custom/lazy-theme.module.ts +++ b/src/themes/custom/lazy-theme.module.ts @@ -99,7 +99,7 @@ import { import { LoadingComponent } from './app/shared/loading/loading.component'; import { SearchResultsComponent } from './app/shared/search/search-results/search-results.component'; import { AdminSidebarComponent } from './app/admin/admin-sidebar/admin-sidebar.component'; -import { SearchSettingsComponent } from './app/shared/search-settings/search-settings.component'; +import { SearchSettingsComponent } from './app/shared/search/search-settings/search-settings.component'; const DECLARATIONS = [ FileSectionComponent, From f787491af4b2f516d7e31bdd14b8c094ecd383e3 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 20 Sep 2022 11:33:37 +0200 Subject: [PATCH 24/97] [CST-6153] Fix issue with forgot password page --- src/app/core/eperson/eperson-data.service.spec.ts | 2 +- src/app/core/eperson/eperson-data.service.ts | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/core/eperson/eperson-data.service.spec.ts b/src/app/core/eperson/eperson-data.service.spec.ts index ce0b1f3ee4..d8a4a546e6 100644 --- a/src/app/core/eperson/eperson-data.service.spec.ts +++ b/src/app/core/eperson/eperson-data.service.spec.ts @@ -307,7 +307,7 @@ describe('EPersonDataService', () => { it('should sent a patch request with an uuid, token and new password to the epersons endpoint', () => { service.patchPasswordWithToken('test-uuid', 'test-token', 'test-password'); - const operation = Object.assign({ op: 'add', path: '/password', value: 'test-password' }); + const operation = Object.assign({ op: 'add', path: '/password', value: { password: 'test-password' } }); const expected = new PatchRequest(requestService.generateRequestId(), epersonsEndpoint + '/test-uuid?token=test-token', [operation]); expect(requestService.send).toHaveBeenCalledWith(expected); diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index 8f9312d732..9eab566bf4 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -3,7 +3,10 @@ import { createSelector, select, Store } from '@ngrx/store'; import { Operation } from 'fast-json-patch'; import { Observable } from 'rxjs'; import { find, map, take } from 'rxjs/operators'; -import { EPeopleRegistryCancelEPersonAction, EPeopleRegistryEditEPersonAction } from '../../access-control/epeople-registry/epeople-registry.actions'; +import { + EPeopleRegistryCancelEPersonAction, + EPeopleRegistryEditEPersonAction +} from '../../access-control/epeople-registry/epeople-registry.actions'; import { EPeopleRegistryState } from '../../access-control/epeople-registry/epeople-registry.reducers'; import { AppState } from '../../app.reducer'; import { hasNoValue, hasValue } from '../../shared/empty.util'; @@ -318,7 +321,7 @@ export class EPersonDataService extends IdentifiableDataService impleme patchPasswordWithToken(uuid: string, token: string, password: string): Observable> { const requestId = this.requestService.generateRequestId(); - const operation = Object.assign({ op: 'add', path: '/password', value: password }); + const operation = Object.assign({ op: 'add', path: '/password', value: { 'password': password } }); const hrefObs = this.halService.getEndpoint(this.linkPath).pipe( map((endpoint: string) => this.getIDHref(endpoint, uuid)), From 5099d0b18a4fdd7f0df9a8bae31edb4d558f5210 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 20 Sep 2022 11:41:09 +0200 Subject: [PATCH 25/97] [CST-6153] Show i18n message instead of server error response --- src/app/profile-page/profile-page.component.ts | 3 ++- src/assets/i18n/en.json5 | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index 5432a0303c..63a3f3f00f 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -157,7 +157,8 @@ export class ProfilePageComponent implements OnInit { ); } else { this.notificationsService.error( - this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'error.title'), response.errorMessage + this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'error.title'), + this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'error.change-failed') ); } }); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 3707903823..0c43ccdc73 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -640,7 +640,7 @@ "bitstream-request-a-copy.alert.canDownload2": "here", "bitstream-request-a-copy.header": "Request a copy of the file", - + "bitstream-request-a-copy.intro": "Enter the following information to request a copy for the following item: ", "bitstream-request-a-copy.intro.bitstream.one": "Requesting the following file: ", @@ -2984,7 +2984,7 @@ "process.detail.create" : "Create similar process", "process.detail.actions": "Actions", - + "process.detail.delete.button": "Delete process", "process.detail.delete.header": "Delete process", @@ -3037,7 +3037,7 @@ "process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted", - + "profile.breadcrumbs": "Update Profile", @@ -3093,6 +3093,8 @@ "profile.security.form.notifications.error.title": "Error changing passwords", + "profile.security.form.notifications.error.change-failed": "An error occurred while trying to change the password. Please check if the current password is correct.", + "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", From 81d3b1708f5018777f94731d40ccbce042f97589 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 20 Sep 2022 12:38:13 +0200 Subject: [PATCH 26/97] 94474: Clarify processing message --- src/app/shared/uploader/uploader.component.html | 2 +- src/assets/i18n/ar.json5 | 4 ++-- src/assets/i18n/cs.json5 | 4 ++-- src/assets/i18n/de.json5 | 3 ++- src/assets/i18n/en.json5 | 2 +- src/assets/i18n/es.json5 | 3 ++- src/assets/i18n/fi.json5 | 3 ++- src/assets/i18n/fr.json5 | 3 ++- src/assets/i18n/hu.json5 | 3 ++- src/assets/i18n/ja.json5 | 4 ++-- src/assets/i18n/lv.json5 | 3 ++- src/assets/i18n/nl.json5 | 3 ++- src/assets/i18n/pl.json5 | 4 ++-- src/assets/i18n/pt-BR.json5 | 3 ++- src/assets/i18n/pt-PT.json5 | 3 ++- src/assets/i18n/sw.json5 | 4 ++-- src/assets/i18n/tr.json5 | 2 +- 17 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/app/shared/uploader/uploader.component.html b/src/app/shared/uploader/uploader.component.html index caa94d1709..eaf2949996 100644 --- a/src/app/shared/uploader/uploader.component.html +++ b/src/app/shared/uploader/uploader.component.html @@ -37,7 +37,7 @@ {{ uploader.progress }}% - {{'uploader.processing' | translate}}... + {{'uploader.processing' | translate}}
Date: Tue, 20 Sep 2022 12:48:27 +0200 Subject: [PATCH 27/97] string changes after merge --- src/assets/i18n/bn.json5 | 3 ++- src/assets/i18n/de.json5 | 3 ++- src/assets/i18n/el.json5 | 2 ++ src/assets/i18n/es.json5 | 3 ++- src/assets/i18n/gd.json5 | 3 ++- src/assets/i18n/kk.json5 | 3 ++- src/assets/i18n/lv.json5 | 3 ++- src/assets/i18n/sv.json5 | 4 ++-- src/assets/i18n/tr.json5 | 3 ++- 9 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/assets/i18n/bn.json5 b/src/assets/i18n/bn.json5 index 1bc26d2da4..a29a9a9c40 100644 --- a/src/assets/i18n/bn.json5 +++ b/src/assets/i18n/bn.json5 @@ -6026,7 +6026,8 @@ // "uploader.or": ", or ", "uploader.or": "অথবা", - // "uploader.processing": "Processing", + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "প্রক্রিয়াকরণ", // "uploader.queue-length": "Queue length", diff --git a/src/assets/i18n/de.json5 b/src/assets/i18n/de.json5 index c699ee2575..cbd11e5c3d 100644 --- a/src/assets/i18n/de.json5 +++ b/src/assets/i18n/de.json5 @@ -5381,7 +5381,8 @@ // "uploader.or": ", or ", "uploader.or": ", oder", - // "uploader.processing": "Processing", + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "In Arbeit...", // "uploader.queue-length": "Queue length", diff --git a/src/assets/i18n/el.json5 b/src/assets/i18n/el.json5 index 4d3b57897a..d99856272f 100644 --- a/src/assets/i18n/el.json5 +++ b/src/assets/i18n/el.json5 @@ -2203,6 +2203,8 @@ "uploader.delete.btn-title": "Διαγραφή", "uploader.drag-message": "Σύρετε και αποθέστε τα αρχεία σας εδώ", "uploader.or": ", ή", + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "Επεξεργασία", "uploader.queue-length": "Μέγεθος ουράς", "virtual-metadata.delete-item.info": "Επιλέξτε τους τύπους για τους οποίους θέλετε να αποθηκεύσετε τα εικονικά μεταδεδομένα ως πραγματικά μεταδεδομένα", diff --git a/src/assets/i18n/es.json5 b/src/assets/i18n/es.json5 index b738578fc6..c641d683c4 100644 --- a/src/assets/i18n/es.json5 +++ b/src/assets/i18n/es.json5 @@ -6515,7 +6515,8 @@ // "uploader.or": ", or ", "uploader.or": ", o ", - // "uploader.processing": "Processing", + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "Procesando", // "uploader.queue-length": "Queue length", diff --git a/src/assets/i18n/gd.json5 b/src/assets/i18n/gd.json5 index f72c3aa1c8..09938fcf5d 100644 --- a/src/assets/i18n/gd.json5 +++ b/src/assets/i18n/gd.json5 @@ -5980,7 +5980,8 @@ // "uploader.or": ", or ", "uploader.or": ", no ", - // "uploader.processing": "Processing", + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "A' pròiseasadh", // "uploader.queue-length": "Queue length", diff --git a/src/assets/i18n/kk.json5 b/src/assets/i18n/kk.json5 index 56651ceaae..63e7374ed0 100644 --- a/src/assets/i18n/kk.json5 +++ b/src/assets/i18n/kk.json5 @@ -7135,7 +7135,8 @@ // "uploader.or": ", or ", "uploader.or": ", немесе ", - // "uploader.processing": "Processing", + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "Өңдеу", // "uploader.queue-length": "Queue length", diff --git a/src/assets/i18n/lv.json5 b/src/assets/i18n/lv.json5 index d6c409b783..8aea8da6e5 100644 --- a/src/assets/i18n/lv.json5 +++ b/src/assets/i18n/lv.json5 @@ -5534,7 +5534,8 @@ // TODO Source message changed - Revise the translation "uploader.or": ", vai", - // "uploader.processing": "Processing", + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "Datu apstrāde", // "uploader.queue-length": "Queue length", diff --git a/src/assets/i18n/sv.json5 b/src/assets/i18n/sv.json5 index 0339969b31..220c5a7f67 100644 --- a/src/assets/i18n/sv.json5 +++ b/src/assets/i18n/sv.json5 @@ -7945,8 +7945,8 @@ // TODO New key - Add a translation "uploader.or": ", eller ", - // "uploader.processing": "Processing", - // TODO New key - Add a translation + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "Bearbetar", // "uploader.queue-length": "Queue length", diff --git a/src/assets/i18n/tr.json5 b/src/assets/i18n/tr.json5 index d04a6eda2a..84e5e0f34b 100644 --- a/src/assets/i18n/tr.json5 +++ b/src/assets/i18n/tr.json5 @@ -5052,7 +5052,8 @@ // "uploader.or": ", or ", "uploader.or": ", veya", - // "uploader.processing": "Processing", + // "uploader.processing": "Processing uploaded file(s)... (it's now safe to close this page)", + // TODO Source message changed - Revise the translation "uploader.processing": "İşleniyor", // "uploader.queue-length": "Queue length", From 2642ed35b78af773324541d2703dba2dc2cb6eff Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 21 Sep 2022 17:47:58 +0200 Subject: [PATCH 28/97] [CST-6153] Use new params name --- src/app/core/eperson/eperson-data.service.spec.ts | 2 +- src/app/core/eperson/eperson-data.service.ts | 2 +- src/app/profile-page/profile-page.component.spec.ts | 4 ++-- src/app/profile-page/profile-page.component.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/core/eperson/eperson-data.service.spec.ts b/src/app/core/eperson/eperson-data.service.spec.ts index d8a4a546e6..b4b939eebf 100644 --- a/src/app/core/eperson/eperson-data.service.spec.ts +++ b/src/app/core/eperson/eperson-data.service.spec.ts @@ -307,7 +307,7 @@ describe('EPersonDataService', () => { it('should sent a patch request with an uuid, token and new password to the epersons endpoint', () => { service.patchPasswordWithToken('test-uuid', 'test-token', 'test-password'); - const operation = Object.assign({ op: 'add', path: '/password', value: { password: 'test-password' } }); + const operation = Object.assign({ op: 'add', path: '/password', value: { new_password: 'test-password' } }); const expected = new PatchRequest(requestService.generateRequestId(), epersonsEndpoint + '/test-uuid?token=test-token', [operation]); expect(requestService.send).toHaveBeenCalledWith(expected); diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index 9eab566bf4..d30030365c 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -321,7 +321,7 @@ export class EPersonDataService extends IdentifiableDataService impleme patchPasswordWithToken(uuid: string, token: string, password: string): Observable> { const requestId = this.requestService.generateRequestId(); - const operation = Object.assign({ op: 'add', path: '/password', value: { 'password': password } }); + const operation = Object.assign({ op: 'add', path: '/password', value: { 'new_password': password } }); const hrefObs = this.halService.getEndpoint(this.linkPath).pipe( map((endpoint: string) => this.getIDHref(endpoint, uuid)), diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index c1bfe8e6bb..709ed56790 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -219,7 +219,7 @@ describe('ProfilePageComponent', () => { component.setCurrentPasswordValue('current-password'); operations = [ - { 'op': 'add', 'path': '/password', 'value': { 'password': 'testest', 'challenge': 'current-password' } } + { 'op': 'add', 'path': '/password', 'value': { 'new_password': 'testest', 'current_password': 'current-password' } } ]; result = component.updateSecurity(); }); @@ -243,7 +243,7 @@ describe('ProfilePageComponent', () => { component.setInvalid(false); component.setCurrentPasswordValue('current-password'); operations = [ - { 'op': 'add', 'path': '/password', 'value': {'password': 'testest', 'challenge': 'current-password' }} + { 'op': 'add', 'path': '/password', 'value': {'new_password': 'testest', 'current_password': 'current-password' }} ]; result = component.updateSecurity(); epersonService.patch(user, operations).subscribe((response) => { diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index 63a3f3f00f..109b2663f4 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -147,7 +147,7 @@ export class ProfilePageComponent implements OnInit { } if (!this.invalidSecurity && passEntered) { const operations = [ - { 'op': 'add', 'path': '/password', 'value': { 'password': this.password, 'challenge': this.currentPassword } } + { 'op': 'add', 'path': '/password', 'value': { 'new_password': this.password, 'current_password': this.currentPassword } } ] as Operation[]; this.epersonService.patch(this.currentUser, operations).pipe(getFirstCompletedRemoteData()).subscribe((response: RemoteData) => { if (response.hasSucceeded) { From 68def61f20ab8655b2c5720a36025ea84bcbb0ee Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Wed, 21 Sep 2022 19:20:49 +0200 Subject: [PATCH 29/97] Test invalidation of dependent requests --- src/app/core/data/base/base-data.service.spec.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/app/core/data/base/base-data.service.spec.ts b/src/app/core/data/base/base-data.service.spec.ts index acda298d3b..17532f477a 100644 --- a/src/app/core/data/base/base-data.service.spec.ts +++ b/src/app/core/data/base/base-data.service.spec.ts @@ -566,7 +566,7 @@ describe('BaseDataService', () => { beforeEach(() => { getByHrefSpy = spyOn(objectCache, 'getByHref').and.returnValue(observableOf({ requestUUIDs: ['request1', 'request2', 'request3'], - dependentRequestUUIDs: [] + dependentRequestUUIDs: ['request4', 'request5'] })); }); @@ -578,6 +578,8 @@ describe('BaseDataService', () => { expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request1'); expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request2'); expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request3'); + expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request4'); + expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request5'); done(); }); }); @@ -590,6 +592,8 @@ describe('BaseDataService', () => { expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request1'); expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request2'); expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request3'); + expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request4'); + expect(requestService.setStaleByUUID).toHaveBeenCalledWith('request5'); })); it('should return an Observable that only emits true once all requests are stale', () => { @@ -599,9 +603,13 @@ describe('BaseDataService', () => { case 'request1': return cold('--(t|)', BOOLEAN); case 'request2': - return cold('----(t|)', BOOLEAN); - case 'request3': return cold('------(t|)', BOOLEAN); + case 'request3': + return cold('---(t|)', BOOLEAN); + case 'request4': + return cold('-(t|)', BOOLEAN); + case 'request5': + return cold('----(t|)', BOOLEAN); } }); From d4107e3f9aea1761b5c7fb01e14b42f4b0bbf142 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Wed, 21 Sep 2022 12:13:10 -0700 Subject: [PATCH 30/97] Initial update for multiple bundle check. --- .../mirador-viewer.component.spec.ts | 5 ++ .../mirador-viewer.component.ts | 10 ++- .../mirador-viewer/mirador-viewer.service.ts | 74 +++++++++++++------ 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/app/item-page/mirador-viewer/mirador-viewer.component.spec.ts b/src/app/item-page/mirador-viewer/mirador-viewer.component.spec.ts index 645d2af91d..40ad0fd5d0 100644 --- a/src/app/item-page/mirador-viewer/mirador-viewer.component.spec.ts +++ b/src/app/item-page/mirador-viewer/mirador-viewer.component.spec.ts @@ -12,6 +12,7 @@ import { createPaginatedList } from '../../shared/testing/utils.test'; import { of as observableOf } from 'rxjs'; import { MiradorViewerService } from './mirador-viewer.service'; import { HostWindowService } from '../../shared/host-window.service'; +import { BundleDataService } from '../../core/data/bundle-data.service'; function getItem(metadata: MetadataMap) { @@ -46,6 +47,7 @@ describe('MiradorViewerComponent with search', () => { declarations: [MiradorViewerComponent], providers: [ { provide: BitstreamDataService, useValue: {} }, + { provide: BundleDataService, useValue: {} }, { provide: HostWindowService, useValue: mockHostWindowService } ], schemas: [NO_ERRORS_SCHEMA] @@ -108,6 +110,7 @@ describe('MiradorViewerComponent with multiple images', () => { declarations: [MiradorViewerComponent], providers: [ { provide: BitstreamDataService, useValue: {} }, + { provide: BundleDataService, useValue: {} }, { provide: HostWindowService, useValue: mockHostWindowService } ], schemas: [NO_ERRORS_SCHEMA] @@ -167,6 +170,7 @@ describe('MiradorViewerComponent with a single image', () => { declarations: [MiradorViewerComponent], providers: [ { provide: BitstreamDataService, useValue: {} }, + { provide: BundleDataService, useValue: {} }, { provide: HostWindowService, useValue: mockHostWindowService } ], schemas: [NO_ERRORS_SCHEMA] @@ -225,6 +229,7 @@ describe('MiradorViewerComponent in development mode', () => { set: { providers: [ { provide: MiradorViewerService, useValue: viewerService }, + { provide: BundleDataService, useValue: {} }, { provide: HostWindowService, useValue: mockHostWindowService } ] } diff --git a/src/app/item-page/mirador-viewer/mirador-viewer.component.ts b/src/app/item-page/mirador-viewer/mirador-viewer.component.ts index 8876d2cea0..bcc50c5ed4 100644 --- a/src/app/item-page/mirador-viewer/mirador-viewer.component.ts +++ b/src/app/item-page/mirador-viewer/mirador-viewer.component.ts @@ -8,6 +8,7 @@ import { map, take } from 'rxjs/operators'; import { isPlatformBrowser } from '@angular/common'; import { MiradorViewerService } from './mirador-viewer.service'; import { HostWindowService, WidthCategory } from '../../shared/host-window.service'; +import { BundleDataService } from '../../core/data/bundle-data.service'; @Component({ selector: 'ds-mirador-viewer', @@ -55,6 +56,7 @@ export class MiradorViewerComponent implements OnInit { constructor(private sanitizer: DomSanitizer, private viewerService: MiradorViewerService, private bitstreamDataService: BitstreamDataService, + private bundleDataService: BundleDataService, private hostWindowService: HostWindowService, @Inject(PLATFORM_ID) private platformId: any) { } @@ -120,8 +122,12 @@ export class MiradorViewerComponent implements OnInit { }) ); } else { - // Sets the multi value based on the image count. - this.iframeViewerUrl = this.viewerService.getImageCount(this.object, this.bitstreamDataService).pipe( + // Sets the multi value based on the image count. Any count greater than 1 + // will add the right thumbnail navigation panel to the viewer. + this.iframeViewerUrl = this.viewerService.getImageCount( + this.object, + this.bitstreamDataService, + this.bundleDataService).pipe( map(c => { if (c > 1) { this.multi = true; diff --git a/src/app/item-page/mirador-viewer/mirador-viewer.service.ts b/src/app/item-page/mirador-viewer/mirador-viewer.service.ts index 4bb095b89f..639c8b3d4e 100644 --- a/src/app/item-page/mirador-viewer/mirador-viewer.service.ts +++ b/src/app/item-page/mirador-viewer/mirador-viewer.service.ts @@ -2,13 +2,15 @@ import { Injectable, isDevMode } from '@angular/core'; import { Observable } from 'rxjs'; import { Item } from '../../core/shared/item.model'; import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; -import { last, map, switchMap } from 'rxjs/operators'; +import { filter, last, map, switchMap } from 'rxjs/operators'; import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { Bitstream } from '../../core/shared/bitstream.model'; import { BitstreamFormat } from '../../core/shared/bitstream-format.model'; import { BitstreamDataService } from '../../core/data/bitstream-data.service'; import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; +import { Bundle } from '../../core/shared/bundle.model'; +import { BundleDataService } from '../../core/data/bundle-data.service'; @Injectable() export class MiradorViewerService { @@ -26,32 +28,56 @@ export class MiradorViewerService { } /** - * Returns observable of the number of images in the ORIGINAL bundle + * Returns observable of the number of images found in eligible IIIF bundles. This checks + * only the first 5 bitstreams in each bundle since any count greater than one is + * enough to set the IIIF viewer to use the "multi" image layout. * @param item * @param bitstreamDataService + * @param bundleDataService */ - getImageCount(item: Item, bitstreamDataService: BitstreamDataService): Observable { + getImageCount(item: Item, bitstreamDataService: BitstreamDataService, bundleDataService: BundleDataService): + Observable { let count = 0; - return bitstreamDataService.findAllByItemAndBundleName(item, 'ORIGINAL', { - currentPage: 1, - elementsPerPage: 10 - }, true, true, ...this.LINKS_TO_FOLLOW) - .pipe( - getFirstCompletedRemoteData(), - map((bitstreamsRD: RemoteData>) => bitstreamsRD.payload), - map((paginatedList: PaginatedList) => paginatedList.page), - switchMap((bitstreams: Bitstream[]) => bitstreams), - switchMap((bitstream: Bitstream) => bitstream.format.pipe( - getFirstSucceededRemoteDataPayload(), - map((format: BitstreamFormat) => format) - )), - map((format: BitstreamFormat) => { - if (format.mimetype.includes('image')) { - count++; - } - return count; - }), - last() - ); + return bundleDataService.findAllByItem(item).pipe( + getFirstCompletedRemoteData(), + map((bundlesRD: RemoteData>) => bundlesRD.payload), + map((paginatedList: PaginatedList) => paginatedList.page), + switchMap((bundles: Bundle[]) => bundles), + filter((b: Bundle) => this.isIiifBundle(b.name)), + switchMap((bundle: Bundle) => { + return bitstreamDataService.findAllByItemAndBundleName(item, bundle.name, { + currentPage: 1, + elementsPerPage: 5 + }, true, true, ...this.LINKS_TO_FOLLOW).pipe( + getFirstCompletedRemoteData(), + map((bitstreamsRD: RemoteData>) => bitstreamsRD.payload), + map((paginatedList: PaginatedList) => paginatedList.page), + switchMap((bitstreams: Bitstream[]) => bitstreams), + switchMap((bitstream: Bitstream) => bitstream.format.pipe( + getFirstSucceededRemoteDataPayload(), + map((format: BitstreamFormat) => format) + )), + map((format: BitstreamFormat) => { + if (format.mimetype.includes('image')) { + count++; + } + return count; + }), + last() + ); + })); } + + isIiifBundle(bundleName: string): boolean { + return !( + bundleName === 'OtherContent' || + bundleName === 'LICENSE' || + bundleName === 'THUMBNAIL' || + bundleName === 'TEXT' || + bundleName === 'METADATA' || + bundleName === 'CC-LICENSE' || + bundleName === 'BRANDED_PREVIEW' + ); + } + } From cc3f570da7357c4cb9d5a3484119c9a6fa8aaad1 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Wed, 21 Sep 2022 12:16:22 -0700 Subject: [PATCH 31/97] Updated comments. --- .../mirador-viewer/mirador-viewer.component.ts | 12 ++++++------ .../mirador-viewer/mirador-viewer.service.ts | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/app/item-page/mirador-viewer/mirador-viewer.component.ts b/src/app/item-page/mirador-viewer/mirador-viewer.component.ts index bcc50c5ed4..fee8046272 100644 --- a/src/app/item-page/mirador-viewer/mirador-viewer.component.ts +++ b/src/app/item-page/mirador-viewer/mirador-viewer.component.ts @@ -109,10 +109,10 @@ export class MiradorViewerComponent implements OnInit { this.notMobile = !(category === WidthCategory.XS || category === WidthCategory.SM); }); - // We need to set the multi property to true if the - // item is searchable or when the ORIGINAL bundle contains more - // than 1 image. (The multi property determines whether the - // Mirador side thumbnail navigation panel is shown.) + // Set the multi property. The default mirador configuration adds a right + // thumbnail navigation panel to the viewer when multi is 'true'. + + // Set the multi property to 'true' if the item is searchable. if (this.searchable) { this.multi = true; const observable = of(''); @@ -122,8 +122,8 @@ export class MiradorViewerComponent implements OnInit { }) ); } else { - // Sets the multi value based on the image count. Any count greater than 1 - // will add the right thumbnail navigation panel to the viewer. + // Set the multi property based on the image count in IIIF-eligible bundles. + // Any count greater than 1 sets the value to 'true'. this.iframeViewerUrl = this.viewerService.getImageCount( this.object, this.bitstreamDataService, diff --git a/src/app/item-page/mirador-viewer/mirador-viewer.service.ts b/src/app/item-page/mirador-viewer/mirador-viewer.service.ts index 639c8b3d4e..68be928cfa 100644 --- a/src/app/item-page/mirador-viewer/mirador-viewer.service.ts +++ b/src/app/item-page/mirador-viewer/mirador-viewer.service.ts @@ -28,12 +28,12 @@ export class MiradorViewerService { } /** - * Returns observable of the number of images found in eligible IIIF bundles. This checks - * only the first 5 bitstreams in each bundle since any count greater than one is - * enough to set the IIIF viewer to use the "multi" image layout. + * Returns observable of the number of images found in eligible IIIF bundles. Checks + * the mimetype of the first 5 bitstreams in each bundle. * @param item * @param bitstreamDataService * @param bundleDataService + * @returns the total image count */ getImageCount(item: Item, bitstreamDataService: BitstreamDataService, bundleDataService: BundleDataService): Observable { From 9de6f38ea62a0d1aff76d7b5a4a0988e2460f632 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 23 Sep 2022 10:37:52 +0200 Subject: [PATCH 32/97] [CST-6153] fix merge --- src/assets/i18n/en.json5 | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index bcb5615d1a..df5fd27062 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3091,8 +3091,6 @@ "profile.security.form.notifications.error.change-failed": "An error occurred while trying to change the password. Please check if the current password is correct.", - "profile.security.form.notifications.error.not-long-enough": "The password has to be at least 6 characters long.", - "profile.security.form.notifications.error.not-same": "The provided passwords are not the same.", "profile.security.form.notifications.error.general": "Please fill required fields of security form.", From 5b1e0d3e0d3967b24d8cf236c6ee137ffc95a62b Mon Sep 17 00:00:00 2001 From: Nikunj Sharma Date: Fri, 23 Sep 2022 16:16:22 +0530 Subject: [PATCH 33/97] CST-6685 updated changes --- .../admin-import-batch-page/batch-import-page.component.spec.ts | 2 ++ .../admin-import-batch-page/batch-import-page.component.ts | 1 + src/app/core/data/processes/script-data.service.ts | 2 +- .../import-batch-selector/import-batch-selector.component.ts | 2 +- src/assets/i18n/en.json5 | 2 +- 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts b/src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts index eecf05f543..6c9d84123b 100644 --- a/src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts +++ b/src/app/admin/admin-import-batch-page/batch-import-page.component.spec.ts @@ -101,6 +101,7 @@ describe('BatchImportPageComponent', () => { const parameterValues: ProcessParameter[] = [ Object.assign(new ProcessParameter(), { name: '--zip', value: 'filename.zip' }), ]; + parameterValues.push(Object.assign(new ProcessParameter(), { name: '--add', value: 'filename.zip' })); expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]); }); it('success notification is shown', () => { @@ -121,6 +122,7 @@ describe('BatchImportPageComponent', () => { it('metadata-import script is invoked with --zip fileName and the mockFile and -v validate-only', () => { const parameterValues: ProcessParameter[] = [ Object.assign(new ProcessParameter(), { name: '--zip', value: 'filename.zip' }), + Object.assign(new ProcessParameter(), { name: '--add', value: 'filename.zip' }), Object.assign(new ProcessParameter(), { name: '-v', value: true }), ]; expect(scriptService.invoke).toHaveBeenCalledWith(BATCH_IMPORT_SCRIPT_NAME, parameterValues, [fileMock]); diff --git a/src/app/admin/admin-import-batch-page/batch-import-page.component.ts b/src/app/admin/admin-import-batch-page/batch-import-page.component.ts index 2985aff3aa..8f49ed64b6 100644 --- a/src/app/admin/admin-import-batch-page/batch-import-page.component.ts +++ b/src/app/admin/admin-import-batch-page/batch-import-page.component.ts @@ -78,6 +78,7 @@ export class BatchImportPageComponent { const parameterValues: ProcessParameter[] = [ Object.assign(new ProcessParameter(), { name: '--zip', value: this.fileObject.name }), ]; + parameterValues.push(Object.assign(new ProcessParameter(), { name: '--add', value: this.fileObject.name })); if (this.dso) { parameterValues.push(Object.assign(new ProcessParameter(), { name: '--collection', value: this.dso.uuid })); } diff --git a/src/app/core/data/processes/script-data.service.ts b/src/app/core/data/processes/script-data.service.ts index f362a9c676..58674d4005 100644 --- a/src/app/core/data/processes/script-data.service.ts +++ b/src/app/core/data/processes/script-data.service.ts @@ -24,7 +24,7 @@ import { dataService } from '../base/data-service.decorator'; export const METADATA_IMPORT_SCRIPT_NAME = 'metadata-import'; export const METADATA_EXPORT_SCRIPT_NAME = 'metadata-export'; -export const BATCH_IMPORT_SCRIPT_NAME = 'batch-import'; +export const BATCH_IMPORT_SCRIPT_NAME = 'import'; @Injectable() @dataService(SCRIPT) diff --git a/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts index 2fdae23388..a88aeaff3c 100644 --- a/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/import-batch-selector/import-batch-selector.component.ts @@ -18,7 +18,7 @@ import { Observable, of } from 'rxjs'; }) export class ImportBatchSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { objectType = DSpaceObjectType.DSPACEOBJECT; - selectorTypes = [DSpaceObjectType.COLLECTION, DSpaceObjectType.COMMUNITY]; + selectorTypes = [DSpaceObjectType.COLLECTION]; action = SelectorActionType.IMPORT_BATCH; /** * An event fired when the modal is closed diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 4dd963a5fe..3e48254a6e 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -554,7 +554,7 @@ "admin.metadata-import.page.help": "You can drop or browse CSV files that contain batch metadata operations on files here", - "admin.batch-import.page.help": "You can drop or browse ZIP files that contain batch operations on files here", + "admin.batch-import.page.help": "Select the Collection to import into. Then, drop or browse to a Simple Archive Format (SAF) zip file that includes the Items to import", "admin.metadata-import.page.dropMsg": "Drop a metadata CSV to import", From 2f71dc358b60bfc78d02e079649e361dc64df1bd Mon Sep 17 00:00:00 2001 From: Samuel Cambien Date: Fri, 23 Sep 2022 10:27:27 +0200 Subject: [PATCH 34/97] issue #1404, issue #1762, issue #1763 Add support for line breaks, markdown and mathjax in metadata --- package.json | 3 + .../edit-in-place-field.component.html | 2 +- .../metadata-values.component.html | 19 +- .../metadata-values.component.spec.ts | 2 +- .../metadata-values.component.ts | 19 +- ...item-page-abstract-field.component.spec.ts | 16 +- .../item-page-abstract-field.component.ts | 1 + .../item-page-field.component.html | 7 +- .../item-page-field.component.spec.ts | 82 +++++- .../item-page-field.component.ts | 5 + src/app/shared/shared.module.ts | 4 +- .../truncatable-part.component.html | 2 +- src/app/shared/utils/markdown.pipe.spec.ts | 66 +++++ src/app/shared/utils/markdown.pipe.ts | 70 +++++ src/config/app-config.interface.ts | 2 + src/config/default-app-config.ts | 4 + src/environments/environment.test.ts | 4 +- src/styles/_global-styles.scss | 4 + yarn.lock | 277 +++++++++++++++++- 19 files changed, 562 insertions(+), 27 deletions(-) create mode 100644 src/app/shared/utils/markdown.pipe.spec.ts create mode 100644 src/app/shared/utils/markdown.pipe.ts diff --git a/package.json b/package.json index 278afdf6c3..5c53b41c7f 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,8 @@ "jwt-decode": "^3.1.2", "klaro": "^0.7.10", "lodash": "^4.17.21", + "markdown-it": "^13.0.1", + "markdown-it-mathjax3": "^4.3.1", "mirador": "^3.3.0", "mirador-dl-plugin": "^0.13.0", "mirador-share-plugin": "^0.11.0", @@ -114,6 +116,7 @@ "postcss-cli": "^8.3.0", "reflect-metadata": "^0.1.13", "rxjs": "^6.6.3", + "sanitize-html": "^2.7.2", "sortablejs": "1.13.0", "tslib": "^2.0.0", "url-parse": "^1.5.3", diff --git a/src/app/item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html b/src/app/item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html index f5543af971..46299c1b08 100644 --- a/src/app/item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html +++ b/src/app/item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.html @@ -26,7 +26,7 @@
- {{metadata?.value}} + {{metadata?.value}}