mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Added LocaleService as localization handler
This commit is contained in:
@@ -1,36 +1,22 @@
|
||||
import {
|
||||
async,
|
||||
ComponentFixture,
|
||||
inject,
|
||||
TestBed
|
||||
} from '@angular/core/testing';
|
||||
|
||||
import {
|
||||
CUSTOM_ELEMENTS_SCHEMA,
|
||||
DebugElement
|
||||
} from '@angular/core';
|
||||
|
||||
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
|
||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { Store, StoreModule } from '@ngrx/store';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
|
||||
// Load the implementations that should be tested
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
import { HostWindowState } from './shared/search/host-window.reducer';
|
||||
import { HostWindowResizeAction } from './shared/host-window.actions';
|
||||
|
||||
import { MetadataService } from './core/metadata/metadata.service';
|
||||
|
||||
import { GLOBAL_CONFIG, ENV_CONFIG } from '../config';
|
||||
import { ENV_CONFIG, GLOBAL_CONFIG } from '../config';
|
||||
import { NativeWindowRef, NativeWindowService } from './core/services/window.service';
|
||||
|
||||
import { MockTranslateLoader } from './shared/mocks/mock-translate-loader';
|
||||
import { MockMetadataService } from './shared/mocks/mock-metadata-service';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
import { AngularticsMock } from './shared/mocks/mock-angulartics.service';
|
||||
import { AuthServiceMock } from './shared/mocks/mock-auth.service';
|
||||
import { AuthService } from './core/auth/auth.service';
|
||||
@@ -40,13 +26,11 @@ import { CSSVariableServiceStub } from './shared/testing/css-variable-service-st
|
||||
import { MenuServiceStub } from './shared/testing/menu-service-stub';
|
||||
import { HostWindowService } from './shared/host-window.service';
|
||||
import { HostWindowServiceStub } from './shared/testing/host-window-service-stub';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { RouteService } from './core/services/route.service';
|
||||
import { MockActivatedRoute } from './shared/mocks/mock-active-router';
|
||||
import { MockRouter } from './shared/mocks/mock-router';
|
||||
import { MockCookieService } from './shared/mocks/mock-cookie.service';
|
||||
import { CookieService } from './core/services/cookie.service';
|
||||
import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
|
||||
import { LocaleService } from './core/locale/locale.service';
|
||||
|
||||
let comp: AppComponent;
|
||||
let fixture: ComponentFixture<AppComponent>;
|
||||
@@ -56,6 +40,12 @@ const menuService = new MenuServiceStub();
|
||||
|
||||
describe('App component', () => {
|
||||
|
||||
function getMockLocaleService(): LocaleService {
|
||||
return jasmine.createSpyObj('LocaleService', {
|
||||
setCurrentLanguageCode: jasmine.createSpy('setCurrentLanguageCode')
|
||||
})
|
||||
}
|
||||
|
||||
// async beforeEach
|
||||
beforeEach(async(() => {
|
||||
return TestBed.configureTestingModule({
|
||||
@@ -82,7 +72,7 @@ describe('App component', () => {
|
||||
{ provide: MenuService, useValue: menuService },
|
||||
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
|
||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
||||
{ provide: CookieService, useValue: new MockCookieService()},
|
||||
{ provide: LocaleService, useValue: getMockLocaleService() },
|
||||
AppComponent,
|
||||
RouteService
|
||||
],
|
||||
|
@@ -1,33 +1,36 @@
|
||||
import { delay, filter, map, take } from 'rxjs/operators';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, Inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
HostListener,
|
||||
Inject,
|
||||
OnInit,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { NavigationCancel, NavigationEnd, NavigationStart, Router } from '@angular/router';
|
||||
|
||||
import { BehaviorSubject, combineLatest as combineLatestObservable, Observable, of } from 'rxjs';
|
||||
import { select, Store } from '@ngrx/store';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
|
||||
import { GLOBAL_CONFIG, GlobalConfig } from '../config';
|
||||
|
||||
import { MetadataService } from './core/metadata/metadata.service';
|
||||
import { HostWindowResizeAction } from './shared/host-window.actions';
|
||||
import { HostWindowState } from './shared/search/host-window.reducer';
|
||||
import { NativeWindowRef, NativeWindowService } from './core/services/window.service';
|
||||
import { isAuthenticated } from './core/auth/selectors';
|
||||
import { AuthService } from './core/auth/auth.service';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
import variables from '../styles/_exposed_variables.scss';
|
||||
import { CSSVariableService } from './shared/sass-helper/sass-helper.service';
|
||||
import { MenuService } from './shared/menu/menu.service';
|
||||
import { MenuID } from './shared/menu/initial-menus-state';
|
||||
import { BehaviorSubject, combineLatest as combineLatestObservable, Observable, of } from 'rxjs';
|
||||
import { slideSidebarPadding } from './shared/animations/slide';
|
||||
import { HostWindowService } from './shared/host-window.service';
|
||||
import { Theme } from '../config/theme.inferface';
|
||||
import { isNotEmpty } from './shared/empty.util';
|
||||
import { CookieService } from './core/services/cookie.service';
|
||||
import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
|
||||
|
||||
export const LANG_COOKIE = 'language_cookie';
|
||||
import { LocaleService } from './core/locale/locale.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-app',
|
||||
@@ -58,29 +61,16 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||
private cssService: CSSVariableService,
|
||||
private menuService: MenuService,
|
||||
private windowService: HostWindowService,
|
||||
private cookie: CookieService
|
||||
private localeService: LocaleService
|
||||
) {
|
||||
// Load all the languages that are defined as active from the config file
|
||||
translate.addLangs(config.languages.filter((LangConfig) => LangConfig.active === true).map((a) => a.code));
|
||||
|
||||
// Load the default language from the config file
|
||||
translate.setDefaultLang(config.defaultLanguage);
|
||||
// translate.setDefaultLang(config.defaultLanguage);
|
||||
|
||||
// Attempt to get the language from a cookie
|
||||
const lang = cookie.get(LANG_COOKIE);
|
||||
if (isNotEmpty(lang)) {
|
||||
// Cookie found
|
||||
// Use the language from the cookie
|
||||
translate.use(lang);
|
||||
} else {
|
||||
// Cookie not found
|
||||
// Attempt to get the browser language from the user
|
||||
if (translate.getLangs().includes(translate.getBrowserLang())) {
|
||||
translate.use(translate.getBrowserLang());
|
||||
} else {
|
||||
translate.use(config.defaultLanguage);
|
||||
}
|
||||
}
|
||||
// set the current language code
|
||||
this.localeService.setCurrentLanguageCode();
|
||||
|
||||
angulartics2GoogleAnalytics.startTracking();
|
||||
angulartics2DSpace.startTracking();
|
||||
|
106
src/app/core/locale/locale.service.spec.ts
Normal file
106
src/app/core/locale/locale.service.spec.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { CookieService } from '../services/cookie.service';
|
||||
import { MockCookieService } from '../../shared/mocks/mock-cookie.service';
|
||||
import { MockTranslateLoader } from '../../shared/mocks/mock-translate-loader';
|
||||
import { LANG_COOKIE, LocaleService } from './locale.service';
|
||||
|
||||
describe('LocaleService test suite', () => {
|
||||
let service: LocaleService;
|
||||
let serviceAsAny: any;
|
||||
let cookieService: CookieService;
|
||||
let translateService: TranslateService;
|
||||
let spyOnGet;
|
||||
let spyOnSet;
|
||||
|
||||
const config: any = {
|
||||
defaultLanguage: 'en'
|
||||
};
|
||||
|
||||
const langList = ['en', 'it', 'de'];
|
||||
|
||||
beforeEach(async(() => {
|
||||
return TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: MockTranslateLoader
|
||||
}
|
||||
}),
|
||||
],
|
||||
providers: [
|
||||
{ provide: CookieService, useValue: new MockCookieService() },
|
||||
]
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
cookieService = TestBed.get(CookieService);
|
||||
translateService = TestBed.get(TranslateService);
|
||||
service = new LocaleService(config, cookieService, translateService);
|
||||
serviceAsAny = service;
|
||||
spyOnGet = spyOn(cookieService, 'get');
|
||||
spyOnSet = spyOn(cookieService, 'set');
|
||||
});
|
||||
|
||||
describe('getCurrentLanguageCode', () => {
|
||||
it('should return language saved on cookie', () => {
|
||||
spyOnGet.and.returnValue('de');
|
||||
expect(service.getCurrentLanguageCode()).toBe('de');
|
||||
});
|
||||
|
||||
describe('', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(translateService, 'getLangs').and.returnValue(langList);
|
||||
});
|
||||
|
||||
it('should return language from browser setting', () => {
|
||||
spyOn(translateService, 'getBrowserLang').and.returnValue('it');
|
||||
expect(service.getCurrentLanguageCode()).toBe('it');
|
||||
});
|
||||
|
||||
it('should return default language from config', () => {
|
||||
spyOn(translateService, 'getBrowserLang').and.returnValue('fr');
|
||||
expect(service.getCurrentLanguageCode()).toBe('en');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLanguageCodeFromCookie', () => {
|
||||
it('should return language from cookie', () => {
|
||||
spyOnGet.and.returnValue('de');
|
||||
expect(service.getLanguageCodeFromCookie()).toBe('de');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('saveLanguageCodeToCookie', () => {
|
||||
it('should save language to cookie', () => {
|
||||
service.saveLanguageCodeToCookie('en');
|
||||
expect(spyOnSet).toHaveBeenCalledWith(LANG_COOKIE, 'en');
|
||||
});
|
||||
});
|
||||
|
||||
describe('setCurrentLanguageCode', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(service, 'saveLanguageCodeToCookie');
|
||||
spyOn(translateService, 'use');
|
||||
});
|
||||
|
||||
it('should set the given language', () => {
|
||||
service.setCurrentLanguageCode('it');
|
||||
expect(translateService.use).toHaveBeenCalledWith( 'it');
|
||||
expect(service.saveLanguageCodeToCookie).toHaveBeenCalledWith('it');
|
||||
});
|
||||
|
||||
it('should set the current language', () => {
|
||||
spyOn(service, 'getCurrentLanguageCode').and.returnValue('es');
|
||||
service.setCurrentLanguageCode();
|
||||
expect(translateService.use).toHaveBeenCalledWith( 'es');
|
||||
expect(service.saveLanguageCodeToCookie).toHaveBeenCalledWith('es');
|
||||
});
|
||||
});
|
||||
});
|
76
src/app/core/locale/locale.service.ts
Normal file
76
src/app/core/locale/locale.service.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { isEmpty } from '../../shared/empty.util';
|
||||
import { CookieService } from '../services/cookie.service';
|
||||
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
||||
|
||||
export const LANG_COOKIE = 'language_cookie';
|
||||
|
||||
/**
|
||||
* Service to provide localization handler
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LocaleService {
|
||||
|
||||
constructor(
|
||||
@Inject(GLOBAL_CONFIG) public config: GlobalConfig,
|
||||
private cookie: CookieService,
|
||||
private translate: TranslateService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the language currently used
|
||||
*
|
||||
* @returns {string} The language code
|
||||
*/
|
||||
getCurrentLanguageCode(): string {
|
||||
// Attempt to get the language from a cookie
|
||||
let lang = this.getLanguageCodeFromCookie();
|
||||
if (isEmpty(lang)) {
|
||||
// Cookie not found
|
||||
// Attempt to get the browser language from the user
|
||||
if (this.translate.getLangs().includes(this.translate.getBrowserLang())) {
|
||||
lang = this.translate.getBrowserLang();
|
||||
} else {
|
||||
lang = this.config.defaultLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the language from a cookie
|
||||
*/
|
||||
getLanguageCodeFromCookie(): string {
|
||||
return this.cookie.get(LANG_COOKIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the language currently used
|
||||
*
|
||||
* @param lang
|
||||
* The language to save
|
||||
*/
|
||||
saveLanguageCodeToCookie(lang: string): void {
|
||||
this.cookie.set(LANG_COOKIE, lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the language currently used
|
||||
*
|
||||
* @param lang
|
||||
* The language to set, if it's not provided retrieve default one
|
||||
*/
|
||||
setCurrentLanguageCode(lang?: string): void {
|
||||
if (isEmpty(lang)) {
|
||||
lang = this.getCurrentLanguageCode()
|
||||
}
|
||||
this.translate.use(lang);
|
||||
this.saveLanguageCodeToCookie(lang);
|
||||
}
|
||||
}
|
@@ -1,14 +1,15 @@
|
||||
import {LangSwitchComponent} from './lang-switch.component';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||
|
||||
import { LangSwitchComponent } from './lang-switch.component';
|
||||
import { GLOBAL_CONFIG } from '../../../config';
|
||||
import { LangConfig } from '../../../config/lang-config.interface';
|
||||
import {Observable, of} from 'rxjs';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { MockCookieService } from '../mocks/mock-cookie.service';
|
||||
import { CookieService } from '../../core/services/cookie.service';
|
||||
import { LocaleService } from '../../core/locale/locale.service';
|
||||
|
||||
// This test is completely independent from any message catalogs or keys in the codebase
|
||||
// The translation module is instantiated with these bogus messages that we aren't using anyway.
|
||||
@@ -28,16 +29,19 @@ class CustomLoader implements TranslateLoader {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* tslint:enable:quotemark */
|
||||
/* tslint:enable:object-literal-key-quotes */
|
||||
|
||||
let cookie: CookieService;
|
||||
let localService: any;
|
||||
|
||||
describe('LangSwitchComponent', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
cookie = Object.assign(new MockCookieService());
|
||||
});
|
||||
function getMockLocaleService(): LocaleService {
|
||||
return jasmine.createSpyObj('LocaleService', {
|
||||
setCurrentLanguageCode: jasmine.createSpy('setCurrentLanguageCode')
|
||||
})
|
||||
}
|
||||
|
||||
describe('with English and Deutsch activated, English as default', () => {
|
||||
let component: LangSwitchComponent;
|
||||
@@ -73,7 +77,7 @@ describe('LangSwitchComponent', () => {
|
||||
providers: [
|
||||
TranslateService,
|
||||
{ provide: GLOBAL_CONFIG, useValue: mockConfig },
|
||||
{ provide: CookieService, useValue: cookie }
|
||||
{ provide: LocaleService, useValue: getMockLocaleService() },
|
||||
]
|
||||
}).compileComponents()
|
||||
.then(() => {
|
||||
@@ -83,6 +87,7 @@ describe('LangSwitchComponent', () => {
|
||||
translate.use('en');
|
||||
http = TestBed.get(HttpTestingController);
|
||||
fixture = TestBed.createComponent(LangSwitchComponent);
|
||||
localService = TestBed.get(LocaleService);
|
||||
component = fixture.componentInstance;
|
||||
de = fixture.debugElement;
|
||||
langSwitchElement = de.nativeElement;
|
||||
@@ -111,19 +116,15 @@ describe('LangSwitchComponent', () => {
|
||||
describe('when selecting a language', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(translate, 'use');
|
||||
spyOn(cookie, 'set');
|
||||
const langItem = fixture.debugElement.query(By.css('.dropdown-item')).nativeElement;
|
||||
langItem.click();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should translate the app', () => {
|
||||
expect(translate.use).toHaveBeenCalled();
|
||||
it('should translate the app and set the client\'s language cookie', () => {
|
||||
expect(localService.setCurrentLanguageCode).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set the client\'s language cookie', () => {
|
||||
expect(cookie.set).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -162,7 +163,7 @@ describe('LangSwitchComponent', () => {
|
||||
providers: [
|
||||
TranslateService,
|
||||
{ provide: GLOBAL_CONFIG, useValue: mockConfig },
|
||||
{ provide: CookieService, useValue: cookie }
|
||||
{ provide: LocaleService, useValue: getMockLocaleService() },
|
||||
]
|
||||
}).compileComponents();
|
||||
translate = TestBed.get(TranslateService);
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
||||
import { LangConfig } from '../../../config/lang-config.interface';
|
||||
import { LANG_COOKIE } from '../../app.component';
|
||||
import { CookieService } from '../../core/services/cookie.service';
|
||||
import { LocaleService } from '../../core/locale/locale.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-lang-switch',
|
||||
@@ -26,7 +27,7 @@ export class LangSwitchComponent implements OnInit {
|
||||
constructor(
|
||||
@Inject(GLOBAL_CONFIG) public config: GlobalConfig,
|
||||
public translate: TranslateService,
|
||||
public cookie: CookieService
|
||||
private localeService: LocaleService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -54,8 +55,7 @@ export class LangSwitchComponent implements OnInit {
|
||||
* @param lang The language to switch to
|
||||
*/
|
||||
useLang(lang: string) {
|
||||
this.translate.use(lang);
|
||||
this.cookie.set(LANG_COOKIE, lang);
|
||||
this.localeService.setCurrentLanguageCode(lang);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user