Skip to content

Commit 98f90c8

Browse files
committed
feat(TranslateService): Use the default language as a fallback
Fixes #16
1 parent d50649f commit 98f90c8

File tree

3 files changed

+49
-9
lines changed

3 files changed

+49
-9
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class AppComponent {
4949
var userLang = navigator.language.split('-')[0]; // use navigator lang if available
5050
userLang = /(fr|en)/gi.test(userLang) ? userLang : 'en';
5151

52-
// optional, default is "en"
52+
// this language will be used as a fallback when a translation isn't found in the current language
5353
translate.setDefaultLang('en');
5454

5555
// the lang to use, if the lang isn't available, it will use the current loader to get them
@@ -100,7 +100,7 @@ translate.setTranslation('en', {
100100

101101
#### Methods:
102102
- `useStaticFilesLoader()`: Use a static files loader
103-
- `setDefaultLang(lang: string)`: Sets the default language to use ('en' by default)
103+
- `setDefaultLang(lang: string)`: Sets the default language to use as a fallback
104104
- `use(lang: string): Observable<any>`: Changes the lang currently used
105105
- `getTranslation(lang: string): Observable<any>`: Gets an object of translations for a given language with the current loader
106106
- `setTranslation(lang: string, translations: Object)`: Manually sets an object of translations for a given language

src/translate.service.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export class TranslateService {
6565

6666
private pending: any;
6767
private translations: any = {};
68-
private defaultLang: string = 'en';
68+
private defaultLang: string;
6969
private langs: Array<string>;
7070
private parser: Parser = new Parser();
7171

@@ -81,7 +81,7 @@ export class TranslateService {
8181
}
8282

8383
/**
84-
* Sets the default language to use ('en' by default)
84+
* Sets the default language to use as a fallback
8585
* @param lang
8686
*/
8787
public setDefaultLang(lang: string) {
@@ -163,6 +163,7 @@ export class TranslateService {
163163
if(!key) {
164164
throw new Error('Parameter "key" required');
165165
}
166+
166167
var getParsedResult = (translations: any, key: any) => {
167168
if(!translations) {
168169
return key;
@@ -174,15 +175,23 @@ export class TranslateService {
174175
}
175176
return result;
176177
}
177-
return this.parser.interpolate(translations[key], interpolateParams) || key
178+
var res: string = this.parser.interpolate(translations[key], interpolateParams);
179+
180+
if(typeof res === 'undefined' && this.defaultLang && this.defaultLang !== this.currentLang) {
181+
let translations: any = this.parser.flattenObject(this.translations[this.defaultLang]);
182+
res = this.parser.interpolate(translations[key], interpolateParams);
183+
}
184+
185+
return res || key;
178186
};
187+
179188
// check if we are loading a new translation to use
180189
if(this.pending) {
181190
return this.pending.map((res: any) => {
182191
return getParsedResult(this.parser.flattenObject(res), key);
183192
});
184193
} else {
185-
let translations = this.parser.flattenObject(this.translations[this.currentLang]);
194+
let translations: any = this.parser.flattenObject(this.translations[this.currentLang]);
186195
return Observable.of(getParsedResult(translations, key));
187196
}
188197
}
@@ -200,7 +209,7 @@ export class TranslateService {
200209

201210
private changeLang(lang: string) {
202211
this.currentLang = lang;
203-
this.onLangChange.next({lang: lang, translations: this.translations[lang]});
212+
this.onLangChange.emit({lang: lang, translations: this.translations[lang]});
204213
}
205214

206215
}

tests/translate.service.spec.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ export function main() {
1515
let translate: TranslateService;
1616
var connection: MockConnection; // this will be set when a new connection is emitted from the backend.
1717

18-
var prepareStaticTranslate = () => {
18+
var prepareStaticTranslate = (lang: string = 'en') => {
1919
// this will load translate json files from src/public/i18n
2020
translate.useStaticFilesLoader();
2121

2222
// the lang to use, if the lang isn't available, it will use the current loader to get them
23-
translate.use('en');
23+
translate.use(lang);
2424
};
2525

2626
var mockBackendResponse = (response: string) => {
@@ -40,6 +40,13 @@ export function main() {
4040
backend.connections.subscribe((c: MockConnection) => connection = c);
4141
});
4242

43+
afterEach(() => {
44+
injector = undefined;
45+
backend = undefined;
46+
translate = undefined;
47+
connection = undefined;
48+
});
49+
4350
it('is defined', () => {
4451
expect(TranslateService).toBeDefined();
4552
expect(translate).toBeDefined();
@@ -63,6 +70,19 @@ export function main() {
6370
});
6471
});
6572

73+
it("should fallback to the default language", () => {
74+
prepareStaticTranslate("fr");
75+
76+
translate.setDefaultLang('en');
77+
translate.setTranslation('en', {"TEST": "This is a test"});
78+
79+
translate.get('TEST').subscribe((res: string) => {
80+
expect(res).toEqual('This is a test');
81+
});
82+
83+
mockBackendResponse('{}');
84+
});
85+
6686
it("should return the key when it doesn't find a translation", () => {
6787
prepareStaticTranslate();
6888

@@ -114,5 +134,16 @@ export function main() {
114134
expect(res).toEqual('This is another test');
115135
});
116136
});
137+
138+
it("shouldn't do a request to the backend if you set the translation yourself", (done: Function) => {
139+
translate.setTranslation('en', {"TEST": "This is a test"});
140+
prepareStaticTranslate();
141+
142+
translate.get('TEST').subscribe((res: string) => {
143+
expect(res).toEqual('This is a test');
144+
expect(connection).not.toBeDefined();
145+
done();
146+
});
147+
});
117148
});
118149
}

0 commit comments

Comments
 (0)