forked from DSpace/dspace-angular
-
Notifications
You must be signed in to change notification settings - Fork 26
/
locale.service.ts
193 lines (177 loc) · 5.62 KB
/
locale.service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import { Injectable, Inject } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { isEmpty, isNotEmpty } from '../../shared/empty.util';
import { CookieService } from '../services/cookie.service';
import { environment } from '../../../environments/environment';
import { AuthService } from '../auth/auth.service';
import { Observable, of as observableOf, combineLatest } from 'rxjs';
import { map, take, flatMap } from 'rxjs/operators';
import { NativeWindowService, NativeWindowRef } from '../services/window.service';
export const LANG_COOKIE = 'language_cookie';
/**
* This enum defines the possible origin of the languages
*/
export enum LANG_ORIGIN {
UI,
EPERSON,
BROWSER
}
/**
* Service to provide localization handler
*/
@Injectable({
providedIn: 'root'
})
export class LocaleService {
/**
* Eperson language metadata
*/
EPERSON_LANG_METADATA = 'eperson.language';
constructor(
@Inject(NativeWindowService) protected _window: NativeWindowRef,
protected cookie: CookieService,
protected translate: TranslateService,
protected authService: AuthService) {
}
/**
* 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 = environment.defaultLanguage;
}
}
return lang;
}
/**
* Get the languages list of the user in Accept-Language format
*
* @returns {Observable<string[]>}
*/
getLanguageCodeList(): Observable<string[]> {
const obs$ = combineLatest([
this.authService.isAuthenticated(),
this.authService.isAuthenticationLoaded()
]);
return obs$.pipe(
take(1),
flatMap(([isAuthenticated, isLoaded]) => {
// TODO to enabled again when https://github.com/DSpace/dspace-angular/issues/739 will be resolved
const epersonLang$: Observable<string[]> = observableOf([]);
/* if (isAuthenticated && isLoaded) {
epersonLang$ = this.authService.getAuthenticatedUserFromStore().pipe(
take(1),
map((eperson) => {
const languages: string[] = [];
const ePersonLang = eperson.firstMetadataValue(this.EPERSON_LANG_METADATA);
if (ePersonLang) {
languages.push(...this.setQuality(
[ePersonLang],
LANG_ORIGIN.EPERSON,
!isEmpty(this.translate.currentLang)));
}
return languages;
})
);
}*/
return epersonLang$.pipe(
map((epersonLang: string[]) => {
const languages: string[] = [];
if (this.translate.currentLang) {
languages.push(...this.setQuality(
[this.translate.currentLang],
LANG_ORIGIN.UI,
false));
}
if (isNotEmpty(epersonLang)) {
languages.push(...epersonLang);
}
if (navigator.languages) {
languages.push(...this.setQuality(
Object.assign([], navigator.languages),
LANG_ORIGIN.BROWSER,
!isEmpty(this.translate.currentLang))
);
}
return languages;
})
)
})
);
}
/**
* 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);
}
/**
* Set the quality factor for all element of input array.
* Returns a new array that contains the languages list with the quality value.
* The quality factor indicate the relative degree of preference for the language
* @param languages the languages list
* @param origin origin of language list (UI, EPERSON, BROWSER)
* @param hasOther true if contains other language, false otherwise
*/
setQuality(languages: string[], origin: LANG_ORIGIN, hasOther: boolean): string[] {
const langWithPrior = [];
let idx = 0;
const v = languages.length > 10 ? languages.length : 10;
let divisor: number;
switch (origin) {
case LANG_ORIGIN.EPERSON:
divisor = 2; break;
case LANG_ORIGIN.BROWSER:
divisor = (hasOther ? 10 : 1); break;
default:
divisor = 1;
}
languages.forEach( (lang) => {
let value = lang + ';q=';
let quality = (v - idx++) / v;
quality = ((languages.length > 10) ? quality.toFixed(2) : quality) as number;
value += quality / divisor;
langWithPrior.push(value);
});
return langWithPrior;
}
/**
* Refresh route navigated
*/
public refreshAfterChangeLanguage() {
// Hard redirect to the reload page with a unique number behind it
// so that all state is definitely lost
this._window.nativeWindow.location.href = `/reload/${new Date().getTime()}`;
}
}