This repository was archived by the owner on Dec 8, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathresources.service.ts
129 lines (104 loc) · 3.71 KB
/
resources.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
import {
forwardRef,
Inject,
Injectable,
Optional
} from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { SkyAppAssetsService } from '@blackbaud/skyux-builder/runtime/assets.service';
import { SkyAppLocaleProvider } from '@blackbaud/skyux-builder/runtime/i18n/locale-provider';
import { SkyAppLocaleInfo } from '@blackbaud/skyux-builder/runtime/i18n/locale-info';
const DEFAULT_LOCALE = 'en-US';
const defaultResources: {[key: string]: {message: string}} = {};
function getDefaultObs() {
return Observable.of({
json: (): any => {
return defaultResources;
}
});
}
/**
* An Angular service for interacting with resource strings.
*/
@Injectable()
export class SkyAppResourcesService {
private resourcesObs: Observable<any>;
private httpObs: {[key: string]: Observable<any>} = {};
constructor(
private http: Http,
/* tslint:disable-next-line no-forward-ref */
@Inject(forwardRef(() => SkyAppAssetsService)) private assets: SkyAppAssetsService,
@Optional() private localeProvider: SkyAppLocaleProvider
) { }
/**
* Gets a resource string based on its name.
* @param name The name of the resource string.
*/
public getString(name: string): Observable<string> {
if (!this.resourcesObs) {
let localeObs: Observable<SkyAppLocaleInfo>;
if (this.localeProvider) {
localeObs = this.localeProvider.getLocaleInfo();
} else {
localeObs = Observable.of({
locale: DEFAULT_LOCALE
});
}
this.resourcesObs = localeObs
.switchMap((localeInfo) => {
let obs: Observable<any>;
let resourcesUrl: string;
const locale = localeInfo.locale;
if (locale) {
resourcesUrl =
this.getUrlForLocale(locale) ||
// Try falling back to the non-region-specific language.
this.getUrlForLocale(locale.substr(0, 2));
}
// Finally fall back to the default locale.
resourcesUrl = resourcesUrl || this.getUrlForLocale(DEFAULT_LOCALE);
if (resourcesUrl) {
obs = this.httpObs[resourcesUrl] || this.http
.get(resourcesUrl)
.publishReplay(1)
.refCount()
.catch(() => {
// The resource file for the specified locale failed to load;
// fall back to the default locale if it differs from the specified
// locale.
const defaultResourcesUrl = this.getUrlForLocale(DEFAULT_LOCALE);
if (defaultResourcesUrl && defaultResourcesUrl !== resourcesUrl) {
return this.http.get(defaultResourcesUrl);
}
return getDefaultObs();
});
} else {
obs = getDefaultObs();
}
this.httpObs[resourcesUrl] = obs;
return obs;
})
// Don't keep trying after a failed attempt to load resources, or else
// impure pipes like resources pipe that call this service will keep
// firing requests indefinitely every few milliseconds.
.catch(() => getDefaultObs());
}
return this.resourcesObs.map((result): string => {
let resources: {[key: string]: {message: string}};
try {
// This can fail if the server returns a 200 but the file is invalid.
resources = result.json();
} catch (err) {
resources = defaultResources;
}
if (name in resources) {
return resources[name].message;
}
return name;
});
}
private getUrlForLocale(locale: string): string {
return this.assets.getUrl(`locales/resources_${locale.replace('-', '_')}.json`);
}
}