ng2-translate
Version:
An implementation of angular translate for Angular 2
424 lines (423 loc) • 15.1 kB
JavaScript
import { Injectable, EventEmitter, Optional } from "@angular/core";
import { Observable } from "rxjs/Observable";
import "rxjs/add/observable/of";
import "rxjs/add/operator/share";
import "rxjs/add/operator/map";
import "rxjs/add/operator/merge";
import "rxjs/add/operator/toArray";
import "rxjs/add/operator/take";
import { TranslateParser } from "./translate.parser";
import { isDefined } from "./util";
export var MissingTranslationHandler = (function () {
function MissingTranslationHandler() {
}
return MissingTranslationHandler;
}());
export var TranslateLoader = (function () {
function TranslateLoader() {
}
return TranslateLoader;
}());
export var TranslateStaticLoader = (function () {
function TranslateStaticLoader(http, prefix, suffix) {
if (prefix === void 0) { prefix = "i18n"; }
if (suffix === void 0) { suffix = ".json"; }
this.http = http;
this.prefix = prefix;
this.suffix = suffix;
}
/**
* Gets the translations from the server
* @param lang
* @returns {any}
*/
TranslateStaticLoader.prototype.getTranslation = function (lang) {
return this.http.get(this.prefix + "/" + lang + this.suffix)
.map(function (res) { return res.json(); });
};
return TranslateStaticLoader;
}());
export var TranslateService = (function () {
/**
*
* @param currentLoader An instance of the loader currently used
* @param parser An instance of the parser currently used
* @param missingTranslationHandler A handler for missing translations.
*/
function TranslateService(currentLoader, parser, missingTranslationHandler) {
this.currentLoader = currentLoader;
this.parser = parser;
this.missingTranslationHandler = missingTranslationHandler;
/**
* The lang currently used
*/
this.currentLang = this.defaultLang;
/**
* An EventEmitter to listen to translation change events
* onTranslationChange.subscribe((params: TranslationChangeEvent) => {
* // do something
* });
* @type {EventEmitter<TranslationChangeEvent>}
*/
this.onTranslationChange = new EventEmitter();
/**
* An EventEmitter to listen to lang change events
* onLangChange.subscribe((params: LangChangeEvent) => {
* // do something
* });
* @type {EventEmitter<LangChangeEvent>}
*/
this.onLangChange = new EventEmitter();
/**
* An EventEmitter to listen to default lang change events
* onDefaultLangChange.subscribe((params: DefaultLangChangeEvent) => {
* // do something
* });
* @type {EventEmitter<DefaultLangChangeEvent>}
*/
this.onDefaultLangChange = new EventEmitter();
this.translations = {};
this.langs = [];
}
/**
* Sets the default language to use as a fallback
* @param lang
*/
TranslateService.prototype.setDefaultLang = function (lang) {
var _this = this;
if (lang === this.defaultLang) {
return;
}
var pending = this.retrieveTranslations(lang);
if (typeof pending !== "undefined") {
// on init set the defaultLang immediately
if (!this.defaultLang) {
this.defaultLang = lang;
}
pending.take(1)
.subscribe(function (res) {
_this.changeDefaultLang(lang);
});
}
else {
this.changeDefaultLang(lang);
}
};
/**
* Gets the default language used
* @returns string
*/
TranslateService.prototype.getDefaultLang = function () {
return this.defaultLang;
};
/**
* Changes the lang currently used
* @param lang
* @returns {Observable<*>}
*/
TranslateService.prototype.use = function (lang) {
var _this = this;
var pending = this.retrieveTranslations(lang);
if (typeof pending !== "undefined") {
// on init set the currentLang immediately
if (!this.currentLang) {
this.currentLang = lang;
}
pending.take(1)
.subscribe(function (res) {
_this.changeLang(lang);
});
return pending;
}
else {
this.changeLang(lang);
return Observable.of(this.translations[lang]);
}
};
/**
* Retrieves the given translations
* @param lang
* @returns {Observable<*>}
*/
TranslateService.prototype.retrieveTranslations = function (lang) {
var pending;
// if this language is unavailable, ask for it
if (typeof this.translations[lang] === "undefined") {
pending = this.getTranslation(lang);
}
return pending;
};
/**
* Gets an object of translations for a given language with the current loader
* @param lang
* @returns {Observable<*>}
*/
TranslateService.prototype.getTranslation = function (lang) {
var _this = this;
this.pending = this.currentLoader.getTranslation(lang).share();
this.pending.take(1)
.subscribe(function (res) {
_this.translations[lang] = res;
_this.updateLangs();
_this.pending = undefined;
}, function (err) {
_this.pending = undefined;
});
return this.pending;
};
/**
* Manually sets an object of translations for a given language
* @param lang
* @param translations
* @param shouldMerge
*/
TranslateService.prototype.setTranslation = function (lang, translations, shouldMerge) {
if (shouldMerge === void 0) { shouldMerge = false; }
if (shouldMerge && this.translations[lang]) {
Object.assign(this.translations[lang], translations);
}
else {
this.translations[lang] = translations;
}
this.updateLangs();
this.onTranslationChange.emit({ lang: lang, translations: this.translations[lang] });
};
/**
* Returns an array of currently available langs
* @returns {any}
*/
TranslateService.prototype.getLangs = function () {
return this.langs;
};
/**
* @param langs
* Add available langs
*/
TranslateService.prototype.addLangs = function (langs) {
var _this = this;
langs.forEach(function (lang) {
if (_this.langs.indexOf(lang) === -1) {
_this.langs.push(lang);
}
});
};
/**
* Update the list of available langs
*/
TranslateService.prototype.updateLangs = function () {
this.addLangs(Object.keys(this.translations));
};
/**
* Returns the parsed result of the translations
* @param translations
* @param key
* @param interpolateParams
* @returns {any}
*/
TranslateService.prototype.getParsedResult = function (translations, key, interpolateParams) {
var res;
if (key instanceof Array) {
var result = {}, observables = false;
for (var _i = 0, key_1 = key; _i < key_1.length; _i++) {
var k = key_1[_i];
result[k] = this.getParsedResult(translations, k, interpolateParams);
if (typeof result[k].subscribe === "function") {
observables = true;
}
}
if (observables) {
var mergedObs = void 0;
for (var _a = 0, key_2 = key; _a < key_2.length; _a++) {
var k = key_2[_a];
var obs = typeof result[k].subscribe === "function" ? result[k] : Observable.of(result[k]);
if (typeof mergedObs === "undefined") {
mergedObs = obs;
}
else {
mergedObs = mergedObs.merge(obs);
}
}
return mergedObs.toArray().map(function (arr) {
var obj = {};
arr.forEach(function (value, index) {
obj[key[index]] = value;
});
return obj;
});
}
return result;
}
if (translations) {
res = this.parser.interpolate(this.parser.getValue(translations, key), interpolateParams);
}
if (typeof res === "undefined" && this.defaultLang && this.defaultLang !== this.currentLang) {
res = this.parser.interpolate(this.parser.getValue(this.translations[this.defaultLang], key), interpolateParams);
}
if (!res && this.missingTranslationHandler) {
var params = { key: key, translateService: this };
if (typeof interpolateParams !== 'undefined') {
params.interpolateParams = interpolateParams;
}
res = this.missingTranslationHandler.handle(params);
}
return typeof res !== "undefined" ? res : key;
};
/**
* Gets the translated value of a key (or an array of keys)
* @param key
* @param interpolateParams
* @returns {any} the translated key, or an object of translated keys
*/
TranslateService.prototype.get = function (key, interpolateParams) {
var _this = this;
if (!isDefined(key) || !key.length) {
throw new Error("Parameter \"key\" required");
}
// check if we are loading a new translation to use
if (this.pending) {
return Observable.create(function (observer) {
var onComplete = function (res) {
observer.next(res);
observer.complete();
};
var onError = function (err) {
observer.error(err);
};
_this.pending.subscribe(function (res) {
res = _this.getParsedResult(res, key, interpolateParams);
if (typeof res.subscribe === "function") {
res.subscribe(onComplete, onError);
}
else {
onComplete(res);
}
}, onError);
});
}
else {
var res = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);
if (typeof res.subscribe === "function") {
return res;
}
else {
return Observable.of(res);
}
}
};
/**
* Returns a translation instantly from the internal state of loaded translation.
* All rules regarding the current language, the preferred language of even fallback languages will be used except any promise handling.
* @param key
* @param interpolateParams
* @returns {string}
*/
TranslateService.prototype.instant = function (key, interpolateParams) {
if (!isDefined(key) || !key.length) {
throw new Error("Parameter \"key\" required");
}
var res = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);
if (typeof res.subscribe !== "undefined") {
if (key instanceof Array) {
var obj_1 = {};
key.forEach(function (value, index) {
obj_1[key[index]] = key[index];
});
return obj_1;
}
return key;
}
else {
return res;
}
};
/**
* Sets the translated value of a key
* @param key
* @param value
* @param lang
*/
TranslateService.prototype.set = function (key, value, lang) {
if (lang === void 0) { lang = this.currentLang; }
this.translations[lang][key] = value;
this.updateLangs();
this.onTranslationChange.emit({ lang: lang, translations: this.translations[lang] });
};
/**
* Changes the current lang
* @param lang
*/
TranslateService.prototype.changeLang = function (lang) {
this.currentLang = lang;
this.onLangChange.emit({ lang: lang, translations: this.translations[lang] });
// if there is no default lang, use the one that we just set
if (!this.defaultLang) {
this.changeDefaultLang(lang);
}
};
/**
* Changes the default lang
* @param lang
*/
TranslateService.prototype.changeDefaultLang = function (lang) {
this.defaultLang = lang;
this.onDefaultLangChange.emit({ lang: lang, translations: this.translations[lang] });
};
/**
* Allows to reload the lang file from the file
* @param lang
* @returns {Observable<any>}
*/
TranslateService.prototype.reloadLang = function (lang) {
this.resetLang(lang);
return this.getTranslation(lang);
};
/**
* Deletes inner translation
* @param lang
*/
TranslateService.prototype.resetLang = function (lang) {
this.translations[lang] = undefined;
};
/**
* Returns the language code name from the browser, e.g. "de"
*
* @returns string
*/
TranslateService.prototype.getBrowserLang = function () {
if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
return undefined;
}
var browserLang = window.navigator.languages ? window.navigator.languages[0] : null;
browserLang = browserLang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;
if (browserLang.indexOf('-') !== -1) {
browserLang = browserLang.split('-')[0];
}
if (browserLang.indexOf('_') !== -1) {
browserLang = browserLang.split('_')[0];
}
return browserLang;
};
/**
* Returns the culture language code name from the browser, e.g. "de-DE"
*
* @returns string
*/
TranslateService.prototype.getBrowserCultureLang = function () {
if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
return undefined;
}
var browserCultureLang = window.navigator.languages ? window.navigator.languages[0] : null;
browserCultureLang = browserCultureLang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;
return browserCultureLang;
};
TranslateService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
TranslateService.ctorParameters = function () { return [
{ type: TranslateLoader, },
{ type: TranslateParser, },
{ type: MissingTranslationHandler, decorators: [{ type: Optional },] },
]; };
return TranslateService;
}());