diff --git a/e2e/app.e2e-spec.ts b/e2e/app.e2e-spec.ts index 79b9f251dd..f5ac9094d0 100644 --- a/e2e/app.e2e-spec.ts +++ b/e2e/app.e2e-spec.ts @@ -7,9 +7,9 @@ describe('protractor App', () => { page = new ProtractorPage(); }); - it('should display title "DSpace"', () => { + it('should display translated title "DSpace Angular :: Home"', () => { page.navigateTo(); - expect(page.getPageTitleText()).toEqual('DSpace'); + expect(page.getPageTitleText()).toEqual('DSpace Angular :: Home'); }); it('should display header "Welcome to DSpace"', () => { diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 3388190295..2239d605cc 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -65,12 +65,16 @@ } }, "home": { + "title": "DSpace Angular :: Home", + "description": "", "top-level-communities": { "head": "Communities in DSpace", "help": "Select a community to browse its collections." } }, "search": { + "title": "DSpace Angular :: Search", + "description": "", "form": { "search": "Search", "search_dspace": "Search DSpace" diff --git a/src/app/+home-page/home-page-routing.module.ts b/src/app/+home-page/home-page-routing.module.ts index f70109e3fe..d7dcc18f49 100644 --- a/src/app/+home-page/home-page-routing.module.ts +++ b/src/app/+home-page/home-page-routing.module.ts @@ -6,7 +6,7 @@ import { HomePageComponent } from './home-page.component'; @NgModule({ imports: [ RouterModule.forChild([ - { path: '', component: HomePageComponent, pathMatch: 'full', data: { title: 'DSpace Angular :: Home' } } + { path: '', component: HomePageComponent, pathMatch: 'full', data: { title: 'home.title' } } ]) ] }) diff --git a/src/app/+search-page/search-page-routing.module.ts b/src/app/+search-page/search-page-routing.module.ts index a74a88dcfa..65cca99a34 100644 --- a/src/app/+search-page/search-page-routing.module.ts +++ b/src/app/+search-page/search-page-routing.module.ts @@ -6,7 +6,7 @@ import { SearchPageComponent } from './search-page.component'; @NgModule({ imports: [ RouterModule.forChild([ - { path: '', component: SearchPageComponent, data: { title: 'DSpace Angular :: Search' } } + { path: '', component: SearchPageComponent, data: { title: 'search.title' } } ]) ] }) diff --git a/src/app/core/metadata/metadata.service.spec.ts b/src/app/core/metadata/metadata.service.spec.ts index 803343c12c..6f740b9f18 100644 --- a/src/app/core/metadata/metadata.service.spec.ts +++ b/src/app/core/metadata/metadata.service.spec.ts @@ -3,9 +3,11 @@ import { RouterTestingModule } from '@angular/router/testing'; import { Location, CommonModule } from '@angular/common'; import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { By, Meta, MetaDefinition } from '@angular/platform-browser'; +import { By, Meta, MetaDefinition, Title } from '@angular/platform-browser'; import { Router } from '@angular/router'; +import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; + import { Store, StoreModule } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; @@ -22,12 +24,13 @@ import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { NormalizedItem } from '../cache/models/normalized-item.model'; import { Item } from '../../core/shared/item.model'; +import { NormalizedItem } from '../cache/models/normalized-item.model'; -import { MockRouter } from '../../shared/mocks/mock-router'; -import { MockNormalizedItem } from '../../shared/mocks/mock-normalized-item'; import { MockItem } from '../../shared/mocks/mock-item'; +import { MockNormalizedItem } from '../../shared/mocks/mock-normalized-item'; +import { MockRouter } from '../../shared/mocks/mock-router'; +import { MockTranslateLoader } from '../../shared/mocks/mock-translate-loader'; /* tslint:disable:max-classes-per-file */ @Component({ @@ -47,6 +50,8 @@ describe('MetadataService', () => { let meta: Meta; + let title: Title; + let store: Store; let objectCacheService: ObjectCacheService; @@ -76,6 +81,12 @@ describe('MetadataService', () => { imports: [ CommonModule, StoreModule.forRoot({}), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: MockTranslateLoader + } + }), RouterTestingModule.withRoutes([ { path: 'items/:id', component: DummyItemComponent, pathMatch: 'full', data: { type: NormalizedItem } }, { path: 'other', component: DummyItemComponent, pathMatch: 'full', data: { title: 'Dummy Title', description: 'This is a dummy component for testing!' } } @@ -92,11 +103,13 @@ describe('MetadataService', () => { { provide: RemoteDataBuildService, useValue: remoteDataBuildService }, { provide: GLOBAL_CONFIG, useValue: ENV_CONFIG }, Meta, + Title, MetadataService ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); meta = TestBed.get(Meta); + title = TestBed.get(Title); metadataService = TestBed.get(MetadataService); envConfig = TestBed.get(GLOBAL_CONFIG); @@ -119,6 +132,7 @@ describe('MetadataService', () => { spyOn(remoteDataBuildService, 'build').and.returnValue(MockItem); router.navigate(['/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357']); tick(); + expect(title.getTitle()).toEqual('Test PowerPoint Document'); expect(tagStore.get('citation_title')[0].content).toEqual('Test PowerPoint Document'); expect(tagStore.get('citation_author')[0].content).toEqual('Doe, Jane'); expect(tagStore.get('citation_date')[0].content).toEqual('1650-06-26T19:58:25Z'); @@ -152,6 +166,7 @@ describe('MetadataService', () => { router.navigate(['/other']); tick(); expect(tagStore.size).toEqual(2); + expect(title.getTitle()).toEqual('Dummy Title'); expect(tagStore.get('title')[0].content).toEqual('Dummy Title'); expect(tagStore.get('description')[0].content).toEqual('This is a dummy component for testing!'); })); diff --git a/src/app/core/metadata/metadata.service.ts b/src/app/core/metadata/metadata.service.ts index 60c2004071..4090d2b484 100644 --- a/src/app/core/metadata/metadata.service.ts +++ b/src/app/core/metadata/metadata.service.ts @@ -9,7 +9,10 @@ import { Params, Router } from '@angular/router'; -import { Meta, MetaDefinition } from '@angular/platform-browser'; + +import { Meta, MetaDefinition, Title } from '@angular/platform-browser'; + +import { TranslateService } from '@ngx-translate/core'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { Observable } from 'rxjs/Observable'; @@ -37,7 +40,9 @@ export class MetadataService { private router: Router, private objectCacheService: ObjectCacheService, private remoteDataBuildService: RemoteDataBuildService, + private translate: TranslateService, private meta: Meta, + private title: Title, @Inject(GLOBAL_CONFIG) private envConfig: GlobalConfig ) { // TODO: determine what open graph meta tags are needed and whether @@ -63,7 +68,6 @@ export class MetadataService { } private processRouteChange(routeInfo: any): void { - this.clearMetaTags(); if (routeInfo.params.value.id && routeInfo.data.value.type) { this.objectCacheService.getByUUID(routeInfo.params.value.id, routeInfo.data.value.type) .first().subscribe((normalizedObject: CacheableObject) => { @@ -74,11 +78,17 @@ export class MetadataService { this.currentObject.next(dspaceObject); }); } else { + this.clearMetaTags(); if (routeInfo.data.value.title) { - this.addMetaTag('title', routeInfo.data.value.title); + this.translate.get(routeInfo.data.value.title).take(1).subscribe((translatedTitle: string) => { + this.addMetaTag('title', translatedTitle); + this.title.setTitle(translatedTitle); + }); } if (routeInfo.data.value.description) { - this.addMetaTag('description', routeInfo.data.value.description); + this.translate.get(routeInfo.data.value.description).take(1).subscribe((translatedDescription: string) => { + this.addMetaTag('description', translatedDescription); + }); } } } @@ -100,6 +110,8 @@ export class MetadataService { private setMetaTags(): void { + this.clearMetaTags(); + this.setTitleTag(); this.setDescriptionTag(); @@ -147,6 +159,7 @@ export class MetadataService { private setTitleTag(): void { const value = this.getMetaTagValue('dc.title'); this.addMetaTag('title', value); + this.title.setTitle(value); } /**