From b6c57d548c1fec692b87554714ccee798554e92d Mon Sep 17 00:00:00 2001 From: Olivier Combe Date: Sun, 28 Feb 2016 22:13:18 +0100 Subject: [PATCH] feat(TranslateService): you can now get instant translations with the `instant` method Fixes #20 --- README.md | 3 +- bundles/ng2-translate.js | 60 +++++++++++++---------- src/translate.service.ts | 87 ++++++++++++++++++++++----------- tests/translate.service.spec.ts | 43 ++++++++++++++++ 4 files changed, 138 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index e6043d5e..d3ce9ff9 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,8 @@ translate.setTranslation('en', { - `setTranslation(lang: string, translations: Object)`: Manually sets an object of translations for a given language - `getLangs()`: Returns an array of currently available langs - `get(key: string|Array, interpolateParams?: Object): Observable`: Gets the translated value of a key (or an array of keys) -- `set(key: string, value: string, lang?: string)`: +- `instant(key: string|Array, interpolateParams?: Object): string|Object`: Gets the instant translated value of a key (or an array of keys) +- `set(key: string, value: string, lang?: string)`: set the translated value of a key #### Write & use your own loader If you want to write your own loader, you need to create a class that implements `TranslateLoader`. diff --git a/bundles/ng2-translate.js b/bundles/ng2-translate.js index a0b1a886..c9f7feb0 100644 --- a/bundles/ng2-translate.js +++ b/bundles/ng2-translate.js @@ -265,45 +265,55 @@ System.registerDynamic("src/translate.service", ["angular2/core", "angular2/http TranslateService.prototype.updateLangs = function() { this.langs = Object.keys(this.translations); }; + TranslateService.prototype.getParsedResult = function(translations, key, interpolateParams) { + var res; + if (key instanceof Array) { + var result = {}; + for (var _i = 0, + key_1 = key; _i < key_1.length; _i++) { + var k = key_1[_i]; + result[k] = this.getParsedResult(translations, k, interpolateParams); + } + return result; + } + if (translations) { + res = this.parser.interpolate(translations[key], interpolateParams); + } + if (typeof res === 'undefined' && this.defaultLang && this.defaultLang !== this.currentLang) { + var translations_1 = this.parser.flattenObject(this.translations[this.defaultLang]); + res = this.parser.interpolate(translations_1[key], interpolateParams); + } + if (!res && this.missingTranslationHandler) { + this.missingTranslationHandler.handle(key); + } + return res || key; + }; TranslateService.prototype.get = function(key, interpolateParams) { var _this = this; if (!key) { throw new Error('Parameter "key" required'); } - var getParsedResult = function(translations, key) { - var res; - if (key instanceof Array) { - var result = {}; - for (var _i = 0, - key_1 = key; _i < key_1.length; _i++) { - var k = key_1[_i]; - result[k] = getParsedResult(translations, k); - } - return result; - } - if (translations) { - res = _this.parser.interpolate(translations[key], interpolateParams); - } - if (typeof res === 'undefined' && _this.defaultLang && _this.defaultLang !== _this.currentLang) { - var translations_1 = _this.parser.flattenObject(_this.translations[_this.defaultLang]); - res = _this.parser.interpolate(translations_1[key], interpolateParams); - } - if (!res && _this.missingTranslationHandler) { - _this.missingTranslationHandler.handle(key); - } - return res || key; - }; if (this.pending) { return this.pending.map(function(res) { - return getParsedResult(_this.parser.flattenObject(res), key); + return _this.getParsedResult(_this.parser.flattenObject(res), key, interpolateParams); }); } else { var translations = void 0; if (this.translations[this.currentLang]) { translations = this.parser.flattenObject(this.translations[this.currentLang]); } - return Observable_1.Observable.of(getParsedResult(translations, key)); + return Observable_1.Observable.of(this.getParsedResult(translations, key, interpolateParams)); + } + }; + TranslateService.prototype.instant = function(key, interpolateParams) { + if (!key) { + throw new Error('Parameter "key" required'); + } + var translations; + if (this.translations[this.currentLang]) { + translations = this.parser.flattenObject(this.translations[this.currentLang]); } + return this.getParsedResult(translations, key, interpolateParams); }; TranslateService.prototype.set = function(key, value, lang) { if (lang === void 0) { diff --git a/src/translate.service.ts b/src/translate.service.ts index 3bc88f30..74206e1d 100644 --- a/src/translate.service.ts +++ b/src/translate.service.ts @@ -181,47 +181,54 @@ export class TranslateService { } /** - * Gets the translated value of a key (or an array of keys) + * Returns the parsed result of the translations + * @param translations * @param key * @param interpolateParams - * @returns {any} the translated key, or an object of translated keys + * @returns {any} */ - public get(key: string|Array, interpolateParams?: Object): Observable { - if(!key) { - throw new Error('Parameter "key" required'); - } - - var getParsedResult = (translations: any, key: any) => { - var res: string; + private getParsedResult(translations: any, key: any, interpolateParams?: Object): string { + var res: string; - if(key instanceof Array) { - let result: any = {}; - for (var k of key) { - result[k] = getParsedResult(translations, k); - } - return result; + if(key instanceof Array) { + let result: any = {}; + for (var k of key) { + result[k] = this.getParsedResult(translations, k, interpolateParams); } + return result; + } - if(translations) { - res = this.parser.interpolate(translations[key], interpolateParams); - } + if(translations) { + res = this.parser.interpolate(translations[key], interpolateParams); + } - if(typeof res === 'undefined' && this.defaultLang && this.defaultLang !== this.currentLang) { - let translations: any = this.parser.flattenObject(this.translations[this.defaultLang]); - res = this.parser.interpolate(translations[key], interpolateParams); - } + if(typeof res === 'undefined' && this.defaultLang && this.defaultLang !== this.currentLang) { + let translations: any = this.parser.flattenObject(this.translations[this.defaultLang]); + res = this.parser.interpolate(translations[key], interpolateParams); + } - if(!res && this.missingTranslationHandler) { - this.missingTranslationHandler.handle(key); - } + if(!res && this.missingTranslationHandler) { + this.missingTranslationHandler.handle(key); + } - return res || key; - }; + return 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 + */ + public get(key: string|Array, interpolateParams?: Object): Observable { + if(!key) { + throw new Error('Parameter "key" required'); + } // check if we are loading a new translation to use if(this.pending) { return this.pending.map((res: any) => { - return getParsedResult(this.parser.flattenObject(res), key); + return this.getParsedResult(this.parser.flattenObject(res), key, interpolateParams); }); } else { let translations: any; @@ -230,10 +237,32 @@ export class TranslateService { translations = this.parser.flattenObject(this.translations[this.currentLang]); } - return Observable.of(getParsedResult(translations, key)); + return Observable.of(this.getParsedResult(translations, key, interpolateParams)); } } + /** + * 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} + */ + public instant(key: string|Array, interpolateParams?: Object): string|any { + if(!key) { + throw new Error('Parameter "key" required'); + } + + // check if we are loading a new translation to use + let translations: any; + + if(this.translations[this.currentLang]) { + translations = this.parser.flattenObject(this.translations[this.currentLang]); + } + + return this.getParsedResult(translations, key, interpolateParams); + } + /** * Sets the translated value of a key * @param key diff --git a/tests/translate.service.spec.ts b/tests/translate.service.spec.ts index 7d23b338..f55bd161 100644 --- a/tests/translate.service.spec.ts +++ b/tests/translate.service.spec.ts @@ -74,6 +74,19 @@ export function main() { }); }); + it('should be able to get an array translations', () => { + var translations = {"TEST": "This is a test", "TEST2": "This is another test2"}; + prepareStaticTranslate(); + + // this will request the translation from the backend because we use a static files loader for TranslateService + translate.get(['TEST', 'TEST2']).subscribe((res: string) => { + expect(res).toEqual(translations); + }); + + // mock response after the xhr request, otherwise it will be undefined + mockBackendResponse(JSON.stringify(translations)); + }); + it("should fallback to the default language", () => { prepareStaticTranslate("fr"); @@ -155,6 +168,28 @@ export function main() { done(); }); }); + + it('should be able to get instant translations', () => { + translate.setTranslation('en', {"TEST": "This is a test"}); + prepareStaticTranslate(); + + expect(translate.instant('TEST')).toEqual('This is a test'); + }); + + it('should be able to get instant translations of an array', () => { + var translations = {"TEST": "This is a test", "TEST2": "This is a test2"}; + translate.setTranslation('en', translations); + prepareStaticTranslate(); + + expect(translate.instant(['TEST', 'TEST2'])).toEqual(translations); + }); + + it('should return the key if instant translations are not available', () => { + translate.setTranslation('en', {"TEST": "This is a test"}); + prepareStaticTranslate(); + + expect(translate.instant('TEST2')).toEqual('TEST2'); + }); function prepareMissingTranslationHandler() { class Missing implements MissingTranslationHandler { @@ -185,6 +220,14 @@ export function main() { expect(handler.handle).not.toHaveBeenCalled(); }); }); + + it('should use the MissingTranslationHandler when the key does not exist & we use instant translation', () => { + prepareStaticTranslate(); + let handler = prepareMissingTranslationHandler(); + + translate.instant('nonExistingKey'); + expect(handler.handle).toHaveBeenCalledWith('nonExistingKey'); + }); }); describe('TranslateLoader', () => {