UNPKG

15.1 kBJavaScriptView Raw
1import { Injectable, EventEmitter, Optional } from "@angular/core";
2import { Observable } from "rxjs/Observable";
3import "rxjs/add/observable/of";
4import "rxjs/add/operator/share";
5import "rxjs/add/operator/map";
6import "rxjs/add/operator/merge";
7import "rxjs/add/operator/toArray";
8import "rxjs/add/operator/take";
9import { TranslateParser } from "./translate.parser";
10import { isDefined } from "./util";
11export var MissingTranslationHandler = (function () {
12 function MissingTranslationHandler() {
13 }
14 return MissingTranslationHandler;
15}());
16export var TranslateLoader = (function () {
17 function TranslateLoader() {
18 }
19 return TranslateLoader;
20}());
21export var TranslateStaticLoader = (function () {
22 function TranslateStaticLoader(http, prefix, suffix) {
23 if (prefix === void 0) { prefix = "i18n"; }
24 if (suffix === void 0) { suffix = ".json"; }
25 this.http = http;
26 this.prefix = prefix;
27 this.suffix = suffix;
28 }
29 /**
30 * Gets the translations from the server
31 * @param lang
32 * @returns {any}
33 */
34 TranslateStaticLoader.prototype.getTranslation = function (lang) {
35 return this.http.get(this.prefix + "/" + lang + this.suffix)
36 .map(function (res) { return res.json(); });
37 };
38 return TranslateStaticLoader;
39}());
40export var TranslateService = (function () {
41 /**
42 *
43 * @param currentLoader An instance of the loader currently used
44 * @param parser An instance of the parser currently used
45 * @param missingTranslationHandler A handler for missing translations.
46 */
47 function TranslateService(currentLoader, parser, missingTranslationHandler) {
48 this.currentLoader = currentLoader;
49 this.parser = parser;
50 this.missingTranslationHandler = missingTranslationHandler;
51 /**
52 * The lang currently used
53 */
54 this.currentLang = this.defaultLang;
55 /**
56 * An EventEmitter to listen to translation change events
57 * onTranslationChange.subscribe((params: TranslationChangeEvent) => {
58 * // do something
59 * });
60 * @type {EventEmitter<TranslationChangeEvent>}
61 */
62 this.onTranslationChange = new EventEmitter();
63 /**
64 * An EventEmitter to listen to lang change events
65 * onLangChange.subscribe((params: LangChangeEvent) => {
66 * // do something
67 * });
68 * @type {EventEmitter<LangChangeEvent>}
69 */
70 this.onLangChange = new EventEmitter();
71 /**
72 * An EventEmitter to listen to default lang change events
73 * onDefaultLangChange.subscribe((params: DefaultLangChangeEvent) => {
74 * // do something
75 * });
76 * @type {EventEmitter<DefaultLangChangeEvent>}
77 */
78 this.onDefaultLangChange = new EventEmitter();
79 this.translations = {};
80 this.langs = [];
81 }
82 /**
83 * Sets the default language to use as a fallback
84 * @param lang
85 */
86 TranslateService.prototype.setDefaultLang = function (lang) {
87 var _this = this;
88 if (lang === this.defaultLang) {
89 return;
90 }
91 var pending = this.retrieveTranslations(lang);
92 if (typeof pending !== "undefined") {
93 // on init set the defaultLang immediately
94 if (!this.defaultLang) {
95 this.defaultLang = lang;
96 }
97 pending.take(1)
98 .subscribe(function (res) {
99 _this.changeDefaultLang(lang);
100 });
101 }
102 else {
103 this.changeDefaultLang(lang);
104 }
105 };
106 /**
107 * Gets the default language used
108 * @returns string
109 */
110 TranslateService.prototype.getDefaultLang = function () {
111 return this.defaultLang;
112 };
113 /**
114 * Changes the lang currently used
115 * @param lang
116 * @returns {Observable<*>}
117 */
118 TranslateService.prototype.use = function (lang) {
119 var _this = this;
120 var pending = this.retrieveTranslations(lang);
121 if (typeof pending !== "undefined") {
122 // on init set the currentLang immediately
123 if (!this.currentLang) {
124 this.currentLang = lang;
125 }
126 pending.take(1)
127 .subscribe(function (res) {
128 _this.changeLang(lang);
129 });
130 return pending;
131 }
132 else {
133 this.changeLang(lang);
134 return Observable.of(this.translations[lang]);
135 }
136 };
137 /**
138 * Retrieves the given translations
139 * @param lang
140 * @returns {Observable<*>}
141 */
142 TranslateService.prototype.retrieveTranslations = function (lang) {
143 var pending;
144 // if this language is unavailable, ask for it
145 if (typeof this.translations[lang] === "undefined") {
146 pending = this.getTranslation(lang);
147 }
148 return pending;
149 };
150 /**
151 * Gets an object of translations for a given language with the current loader
152 * @param lang
153 * @returns {Observable<*>}
154 */
155 TranslateService.prototype.getTranslation = function (lang) {
156 var _this = this;
157 this.pending = this.currentLoader.getTranslation(lang).share();
158 this.pending.take(1)
159 .subscribe(function (res) {
160 _this.translations[lang] = res;
161 _this.updateLangs();
162 _this.pending = undefined;
163 }, function (err) {
164 _this.pending = undefined;
165 });
166 return this.pending;
167 };
168 /**
169 * Manually sets an object of translations for a given language
170 * @param lang
171 * @param translations
172 * @param shouldMerge
173 */
174 TranslateService.prototype.setTranslation = function (lang, translations, shouldMerge) {
175 if (shouldMerge === void 0) { shouldMerge = false; }
176 if (shouldMerge && this.translations[lang]) {
177 Object.assign(this.translations[lang], translations);
178 }
179 else {
180 this.translations[lang] = translations;
181 }
182 this.updateLangs();
183 this.onTranslationChange.emit({ lang: lang, translations: this.translations[lang] });
184 };
185 /**
186 * Returns an array of currently available langs
187 * @returns {any}
188 */
189 TranslateService.prototype.getLangs = function () {
190 return this.langs;
191 };
192 /**
193 * @param langs
194 * Add available langs
195 */
196 TranslateService.prototype.addLangs = function (langs) {
197 var _this = this;
198 langs.forEach(function (lang) {
199 if (_this.langs.indexOf(lang) === -1) {
200 _this.langs.push(lang);
201 }
202 });
203 };
204 /**
205 * Update the list of available langs
206 */
207 TranslateService.prototype.updateLangs = function () {
208 this.addLangs(Object.keys(this.translations));
209 };
210 /**
211 * Returns the parsed result of the translations
212 * @param translations
213 * @param key
214 * @param interpolateParams
215 * @returns {any}
216 */
217 TranslateService.prototype.getParsedResult = function (translations, key, interpolateParams) {
218 var res;
219 if (key instanceof Array) {
220 var result = {}, observables = false;
221 for (var _i = 0, key_1 = key; _i < key_1.length; _i++) {
222 var k = key_1[_i];
223 result[k] = this.getParsedResult(translations, k, interpolateParams);
224 if (typeof result[k].subscribe === "function") {
225 observables = true;
226 }
227 }
228 if (observables) {
229 var mergedObs = void 0;
230 for (var _a = 0, key_2 = key; _a < key_2.length; _a++) {
231 var k = key_2[_a];
232 var obs = typeof result[k].subscribe === "function" ? result[k] : Observable.of(result[k]);
233 if (typeof mergedObs === "undefined") {
234 mergedObs = obs;
235 }
236 else {
237 mergedObs = mergedObs.merge(obs);
238 }
239 }
240 return mergedObs.toArray().map(function (arr) {
241 var obj = {};
242 arr.forEach(function (value, index) {
243 obj[key[index]] = value;
244 });
245 return obj;
246 });
247 }
248 return result;
249 }
250 if (translations) {
251 res = this.parser.interpolate(this.parser.getValue(translations, key), interpolateParams);
252 }
253 if (typeof res === "undefined" && this.defaultLang && this.defaultLang !== this.currentLang) {
254 res = this.parser.interpolate(this.parser.getValue(this.translations[this.defaultLang], key), interpolateParams);
255 }
256 if (!res && this.missingTranslationHandler) {
257 var params = { key: key, translateService: this };
258 if (typeof interpolateParams !== 'undefined') {
259 params.interpolateParams = interpolateParams;
260 }
261 res = this.missingTranslationHandler.handle(params);
262 }
263 return typeof res !== "undefined" ? res : key;
264 };
265 /**
266 * Gets the translated value of a key (or an array of keys)
267 * @param key
268 * @param interpolateParams
269 * @returns {any} the translated key, or an object of translated keys
270 */
271 TranslateService.prototype.get = function (key, interpolateParams) {
272 var _this = this;
273 if (!isDefined(key) || !key.length) {
274 throw new Error("Parameter \"key\" required");
275 }
276 // check if we are loading a new translation to use
277 if (this.pending) {
278 return Observable.create(function (observer) {
279 var onComplete = function (res) {
280 observer.next(res);
281 observer.complete();
282 };
283 var onError = function (err) {
284 observer.error(err);
285 };
286 _this.pending.subscribe(function (res) {
287 res = _this.getParsedResult(res, key, interpolateParams);
288 if (typeof res.subscribe === "function") {
289 res.subscribe(onComplete, onError);
290 }
291 else {
292 onComplete(res);
293 }
294 }, onError);
295 });
296 }
297 else {
298 var res = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);
299 if (typeof res.subscribe === "function") {
300 return res;
301 }
302 else {
303 return Observable.of(res);
304 }
305 }
306 };
307 /**
308 * Returns a translation instantly from the internal state of loaded translation.
309 * All rules regarding the current language, the preferred language of even fallback languages will be used except any promise handling.
310 * @param key
311 * @param interpolateParams
312 * @returns {string}
313 */
314 TranslateService.prototype.instant = function (key, interpolateParams) {
315 if (!isDefined(key) || !key.length) {
316 throw new Error("Parameter \"key\" required");
317 }
318 var res = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);
319 if (typeof res.subscribe !== "undefined") {
320 if (key instanceof Array) {
321 var obj_1 = {};
322 key.forEach(function (value, index) {
323 obj_1[key[index]] = key[index];
324 });
325 return obj_1;
326 }
327 return key;
328 }
329 else {
330 return res;
331 }
332 };
333 /**
334 * Sets the translated value of a key
335 * @param key
336 * @param value
337 * @param lang
338 */
339 TranslateService.prototype.set = function (key, value, lang) {
340 if (lang === void 0) { lang = this.currentLang; }
341 this.translations[lang][key] = value;
342 this.updateLangs();
343 this.onTranslationChange.emit({ lang: lang, translations: this.translations[lang] });
344 };
345 /**
346 * Changes the current lang
347 * @param lang
348 */
349 TranslateService.prototype.changeLang = function (lang) {
350 this.currentLang = lang;
351 this.onLangChange.emit({ lang: lang, translations: this.translations[lang] });
352 // if there is no default lang, use the one that we just set
353 if (!this.defaultLang) {
354 this.changeDefaultLang(lang);
355 }
356 };
357 /**
358 * Changes the default lang
359 * @param lang
360 */
361 TranslateService.prototype.changeDefaultLang = function (lang) {
362 this.defaultLang = lang;
363 this.onDefaultLangChange.emit({ lang: lang, translations: this.translations[lang] });
364 };
365 /**
366 * Allows to reload the lang file from the file
367 * @param lang
368 * @returns {Observable<any>}
369 */
370 TranslateService.prototype.reloadLang = function (lang) {
371 this.resetLang(lang);
372 return this.getTranslation(lang);
373 };
374 /**
375 * Deletes inner translation
376 * @param lang
377 */
378 TranslateService.prototype.resetLang = function (lang) {
379 this.translations[lang] = undefined;
380 };
381 /**
382 * Returns the language code name from the browser, e.g. "de"
383 *
384 * @returns string
385 */
386 TranslateService.prototype.getBrowserLang = function () {
387 if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
388 return undefined;
389 }
390 var browserLang = window.navigator.languages ? window.navigator.languages[0] : null;
391 browserLang = browserLang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;
392 if (browserLang.indexOf('-') !== -1) {
393 browserLang = browserLang.split('-')[0];
394 }
395 if (browserLang.indexOf('_') !== -1) {
396 browserLang = browserLang.split('_')[0];
397 }
398 return browserLang;
399 };
400 /**
401 * Returns the culture language code name from the browser, e.g. "de-DE"
402 *
403 * @returns string
404 */
405 TranslateService.prototype.getBrowserCultureLang = function () {
406 if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
407 return undefined;
408 }
409 var browserCultureLang = window.navigator.languages ? window.navigator.languages[0] : null;
410 browserCultureLang = browserCultureLang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;
411 return browserCultureLang;
412 };
413 TranslateService.decorators = [
414 { type: Injectable },
415 ];
416 /** @nocollapse */
417 TranslateService.ctorParameters = function () { return [
418 { type: TranslateLoader, },
419 { type: TranslateParser, },
420 { type: MissingTranslationHandler, decorators: [{ type: Optional },] },
421 ]; };
422 return TranslateService;
423}());