Skip to content

Commit 27a1ca2

Browse files
committed
Refactoring: Moved translation data management into store.
1 parent 5ebd7a5 commit 27a1ca2

File tree

4 files changed

+172
-134
lines changed

4 files changed

+172
-134
lines changed

projects/ngx-translate/src/lib/translate.service.spec.ts

+4-10
Original file line numberDiff line numberDiff line change
@@ -799,26 +799,20 @@ describe("TranslateService", () =>
799799
it("should be able to add new languages", () =>
800800
{
801801
translate.addLangs(["pl", "es"]);
802-
expect(translate.getLangs()).toEqual(["pl", "es"]);
802+
expect(translate.langs).toEqual(["pl", "es"]);
803803
translate.addLangs(["fr"]);
804804
translate.addLangs(["pl", "fr"]);
805-
expect(translate.getLangs()).toEqual(["pl", "es", "fr"]);
805+
expect(translate.langs).toEqual(["pl", "es", "fr"]);
806806

807807
// this will request the translation from the backend because we use a static files loader for TranslateService
808808
translate.use("en").subscribe(() =>
809809
{
810-
expect(translate.getLangs()).toEqual(["pl", "es", "fr", "en"]);
810+
expect(translate.langs).toEqual(["pl", "es", "fr", "en"]);
811811
translate.addLangs(["de"]);
812-
expect(translate.getLangs()).toEqual(["pl", "es", "fr", "en", "de"]);
812+
expect(translate.langs).toEqual(["pl", "es", "fr", "en", "de"]);
813813
});
814814
});
815815

816-
it("should be able to set the langs property directly", () =>
817-
{
818-
translate.langs = ["pl", "es"];
819-
expect(translate.getLangs()).toEqual(["pl", "es"]);
820-
});
821-
822816
it("should be able to get the browserLang", () =>
823817
{
824818
const browserLang = translate.getBrowserLang();

projects/ngx-translate/src/lib/translate.service.ts

+49-92
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {TranslateCompiler} from "./translate.compiler";
66
import {TranslateLoader} from "./translate.loader";
77
import {InterpolateFunction, TranslateParser} from "./translate.parser";
88
import {TranslateStore} from "./translate.store";
9-
import {getValue, isDefined, isArray, isString, mergeDeep, setValue, isDict} from "./util";
9+
import {getValue, isDefined, isArray, isString, setValue, isDict, insertValue} from "./util";
1010

1111
export const ISOLATE_TRANSLATE_SERVICE = new InjectionToken<string>('ISOLATE_TRANSLATE_SERVICE');
1212
export const USE_DEFAULT_LANG = new InjectionToken<string>('USE_DEFAULT_LANG');
@@ -91,8 +91,8 @@ const makeObservable = <T>(value: T | Observable<T>): Observable<T> => {
9191
export class TranslateService {
9292
private loadingTranslations!: Observable<InterpolatableTranslationObject>;
9393
private pending = false;
94-
private _translationRequests: Record<string, Observable<TranslationObject>> = {};
95-
private lastUseLanguage: string|null = null;
94+
private _translationRequests: Record<Language, Observable<TranslationObject>> = {};
95+
private lastUseLanguage: Language|null = null;
9696

9797

9898
/**
@@ -128,45 +128,22 @@ export class TranslateService {
128128
/**
129129
* The default lang to fallback when translations are missing on the current lang
130130
*/
131-
get defaultLang(): string {
132-
return this.store.defaultLang;
133-
}
134-
135-
set defaultLang(defaultLang: string) {
136-
this.store.defaultLang = defaultLang;
131+
get defaultLang(): Language {
132+
return this.store.getDefaultLanguage();
137133
}
138134

139135
/**
140136
* The lang currently used
141137
*/
142-
get currentLang(): string {
143-
return this.store.currentLang;
144-
}
145-
146-
set currentLang(currentLang: string) {
147-
this.store.currentLang = currentLang;
138+
get currentLang(): Language {
139+
return this.store.getCurrentLanguage();
148140
}
149141

150142
/**
151143
* an array of langs
152144
*/
153-
get langs(): string[] {
154-
return this.store.langs;
155-
}
156-
157-
set langs(langs: string[]) {
158-
this.store.langs = langs;
159-
}
160-
161-
/**
162-
* a list of translations per lang
163-
*/
164-
get translations(): Record<string, InterpolatableTranslationObject> {
165-
return this.store.translations;
166-
}
167-
168-
set translations(translations: Record<string, InterpolatableTranslationObject>) {
169-
this.store.translations = translations;
145+
get langs(): readonly Language[] {
146+
return this.store.getLanguages();
170147
}
171148

172149
/**
@@ -213,17 +190,21 @@ export class TranslateService {
213190
const pending = this.retrieveTranslations(lang);
214191

215192
if (typeof pending !== "undefined") {
216-
// on init set the defaultLang immediately
193+
217194
if (this.defaultLang == null) {
218-
this.defaultLang = lang;
195+
// on init set the defaultLang immediately
196+
// but do not emit the change yet
197+
this.store.setDefaultLang(lang, false);
219198
}
220199

221200
pending.pipe(take(1))
222201
.subscribe(() => {
223-
this.changeDefaultLang(lang);
202+
this.store.setDefaultLang(lang);
224203
});
225-
} else { // we already have this language
226-
this.changeDefaultLang(lang);
204+
}
205+
else {
206+
// we already have this language
207+
this.store.setDefaultLang(lang);
227208
}
228209
}
229210

@@ -246,12 +227,12 @@ export class TranslateService {
246227

247228
// don't change the language if the language given is already selected
248229
if (lang === this.currentLang) {
249-
return of(this.translations[lang]);
230+
return of(this.store.getTranslations(lang));
250231
}
251232

252233
// on init set the currentLang immediately
253234
if (!this.currentLang) {
254-
this.currentLang = lang;
235+
this.store.setCurrentLang(lang, false);
255236
}
256237

257238
const pending = this.retrieveTranslations(lang);
@@ -268,7 +249,7 @@ export class TranslateService {
268249
else {
269250
// we have this language, return an Observable
270251
this.changeLang(lang);
271-
return of(this.translations[lang]);
252+
return of(this.store.getTranslations(lang));
272253
}
273254
}
274255

@@ -278,20 +259,18 @@ export class TranslateService {
278259
*/
279260
private changeLang(lang: string): void {
280261

281-
// received a new language file
282-
// but this was not the one requested last
283262
if(lang !== this.lastUseLanguage)
284263
{
264+
// received new language data,
265+
// but this was not the one requested last
285266
return;
286267
}
287268

288-
this.currentLang = lang;
289-
290-
this.store.emitLangChange({lang: lang, translations: this.translations[lang]});
269+
this.store.setCurrentLang(lang);
291270

292-
// if there is no default lang, use the one that we just set
293271
if (this.defaultLang == null) {
294-
this.changeDefaultLang(lang);
272+
// if there is no default lang, use the one that we just set
273+
this.store.setDefaultLang(lang);
295274
}
296275
}
297276

@@ -302,7 +281,7 @@ export class TranslateService {
302281
private retrieveTranslations(lang: string): Observable<TranslationObject> | undefined {
303282

304283
// if this language is unavailable or extend is true, ask for it
305-
if (typeof this.translations[lang] === "undefined" || this.extend) {
284+
if (!this.store.hasTranslationFor(lang) || this.extend) {
306285
this._translationRequests[lang] = this._translationRequests[lang] || this.loadAndCompileTranslations(lang);
307286
return this._translationRequests[lang];
308287
}
@@ -344,8 +323,7 @@ export class TranslateService {
344323
this.loadingTranslations
345324
.subscribe({
346325
next: (res: InterpolatableTranslationObject) => {
347-
this.translations[lang] = (this.extend && this.translations[lang]) ? { ...res, ...this.translations[lang] } : res;
348-
this.updateLangs();
326+
this.store.setTranslations(lang, res, this.extend);
349327
this.pending = false;
350328
},
351329
error: (err) => {
@@ -361,41 +339,24 @@ export class TranslateService {
361339
* Manually sets an object of translations for a given language
362340
* after passing it through the compiler
363341
*/
364-
public setTranslation(lang: string, translations: InterpolatableTranslationObject, shouldMerge = false): void {
342+
public setTranslation(lang: Language, translations: InterpolatableTranslationObject, shouldMerge = false): void {
365343
const interpolatableTranslations = this.compiler.compileTranslations(translations, lang);
366-
if ((shouldMerge || this.extend) && this.translations[lang]) {
367-
this.translations[lang] = mergeDeep(this.translations[lang], interpolatableTranslations);
368-
} else {
369-
this.translations[lang] = interpolatableTranslations;
370-
}
371-
this.updateLangs();
372-
this.store.emitTranslationChange({lang: lang, translations: this.translations[lang]});
344+
this.store.setTranslations(lang, interpolatableTranslations, (shouldMerge || this.extend));
373345
}
374346

375-
/**
376-
* Returns an array of currently available langs
377-
*/
378-
public getLangs(): string[] {
379-
return this.langs;
347+
348+
public getLangs(): readonly Language[] {
349+
return this.store.getLanguages();
380350
}
381351

382352
/**
383353
* Add available languages
384354
*/
385-
public addLangs(langs: string[]): void
355+
public addLangs(languages: Language[]): void
386356
{
387-
const newLangs = langs.filter(lang => !this.langs.includes(lang));
388-
if (newLangs.length > 0) {
389-
this.langs = [...this.langs, ...newLangs];
390-
}
357+
this.store.addLanguages(languages);
391358
}
392359

393-
/**
394-
* Update the list of available languages
395-
*/
396-
private updateLangs(): void {
397-
this.addLangs(Object.keys(this.translations));
398-
}
399360

400361
private getParsedResultForKey(translations: InterpolatableTranslation, key: string, interpolateParams?: InterpolationParameters): Translation|Observable<Translation>
401362
{
@@ -424,7 +385,7 @@ export class TranslateService {
424385
let text = getValue(translations, key);
425386
if(text === undefined && this.defaultLang != null && this.defaultLang !== this.currentLang && this.useDefaultLang)
426387
{
427-
text = getValue(this.translations[this.defaultLang], key);
388+
text = getValue(this.store.getTranslations(this.defaultLang), key);
428389
}
429390
return text;
430391
}
@@ -504,7 +465,7 @@ export class TranslateService {
504465
);
505466
}
506467

507-
return makeObservable(this.getParsedResult(this.translations[this.currentLang], key, interpolateParams));
468+
return makeObservable(this.getParsedResult(this.store.getTranslations(this.currentLang), key, interpolateParams));
508469
}
509470

510471
/**
@@ -559,7 +520,7 @@ export class TranslateService {
559520
throw new Error('Parameter "key" is required and cannot be empty');
560521
}
561522

562-
const result = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);
523+
const result = this.getParsedResult(this.store.getTranslations(this.currentLang), key, interpolateParams);
563524

564525
if (isObservable(result)) {
565526
if (Array.isArray(key)) {
@@ -577,23 +538,19 @@ export class TranslateService {
577538
/**
578539
* Sets the translated value of a key, after compiling it
579540
*/
580-
public set(key: string, translation: Translation, lang: string = this.currentLang): void {
581-
setValue(this.translations[lang], key,
582-
isString(translation)
583-
? this.compiler.compile(translation, lang)
584-
: this.compiler.compileTranslations(translation, lang)
541+
public set(key: string, translation: Translation, lang: Language = this.currentLang): void {
542+
543+
this.store.setTranslations(
544+
lang,
545+
insertValue(this.store.getTranslations(lang), key,
546+
isString(translation)
547+
? this.compiler.compile(translation, lang)
548+
: this.compiler.compileTranslations(translation, lang)
549+
),
550+
false
585551
);
586-
this.updateLangs();
587-
this.store.emitTranslationChange({lang: lang, translations: this.translations[lang]});
588552
}
589553

590-
/**
591-
* Changes the default lang
592-
*/
593-
private changeDefaultLang(lang: string): void {
594-
this.defaultLang = lang;
595-
this.store.emitDefaultLangChange({lang: lang, translations: this.translations[lang]});
596-
}
597554

598555
/**
599556
* Allows to reload the lang file from the file
@@ -608,7 +565,7 @@ export class TranslateService {
608565
*/
609566
public resetLang(lang: string): void {
610567
delete this._translationRequests[lang];
611-
delete this.translations[lang];
568+
this.store.deleteTranslations(lang);
612569
}
613570

614571
/**

0 commit comments

Comments
 (0)