Skip to content

Commit

Permalink
feat(TranslateService): you can now get instant translations with the…
Browse files Browse the repository at this point in the history
… `instant` method

Fixes #20
  • Loading branch information
ocombe committed Feb 28, 2016
1 parent dd43fa6 commit b6c57d5
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 55 deletions.
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -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<string>, interpolateParams?: Object): Observable<string|Object>`: Gets the translated value of a key (or an array of keys)
- `set(key: string, value: string, lang?: string)`:
- `instant(key: string|Array<string>, 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`.
Expand Down
60 changes: 35 additions & 25 deletions bundles/ng2-translate.js
Expand Up @@ -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) {
Expand Down
87 changes: 58 additions & 29 deletions src/translate.service.ts
Expand Up @@ -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<string>, interpolateParams?: Object): Observable<string|any> {
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<string>, interpolateParams?: Object): Observable<string|any> {
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;
Expand All @@ -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<string>, 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
Expand Down
43 changes: 43 additions & 0 deletions tests/translate.service.spec.ts
Expand Up @@ -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");

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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', () => {
Expand Down

0 comments on commit b6c57d5

Please sign in to comment.