Skip to content

Commit 077b3c8

Browse files
authored
Merge pull request #302 from cal-smith/i18n
fix(i18n): set now does a deep merge
2 parents 8eaf2bd + 0444455 commit 077b3c8

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

src/i18n/i18n.service.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Injectable } from "@angular/core";
22
import { BehaviorSubject } from "rxjs";
33
import { map } from "rxjs/operators";
4+
import { merge } from "./../utils/object";
45

56
const EN = require("./en.json");
67

@@ -35,7 +36,7 @@ export const replace = (subject, variables) => subject.pipe(
3536
);
3637

3738
/**
38-
* The I18n service is a minimal internal service used to supply our components with translated strings.
39+
* The I18n service is a minimal internal singleton service used to supply our components with translated strings.
3940
*
4041
* All the components that support I18n also support directly passed strings.
4142
* Usage of I18n is optional, and it is not recommended for application use (libraries like ngx-translate
@@ -54,7 +55,8 @@ export class I18n {
5455
* @param strings an object of strings, should follow the same format as src/i18n/en.json
5556
*/
5657
public set(strings) {
57-
this.translationStrings = Object.assign({}, EN, strings);
58+
this.translationStrings = merge({}, EN, strings);
59+
// iterate over all our tracked translations and update each observable
5860
const translations = Array.from(this.translations);
5961
for (const [path, subject] of translations) {
6062
subject.next(this.getValueFromPath(path));

src/i18n/i18n.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,11 @@ describe("i18n service", () => {
6161
done();
6262
});
6363
});
64+
65+
it("should keep the default translation strings", () => {
66+
service.set({ "BANNER": { "TEST": "TEST" } });
67+
68+
expect(service.get().BANNER.CLOSE_BUTTON).toBe(EN.BANNER.CLOSE_BUTTON);
69+
expect(service.get().BANNER.TEST).toBe("TEST");
70+
});
6471
});

src/utils/object.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// custom deep object merge
2+
export const merge = (target, ...objects) => {
3+
for (const object of objects) {
4+
for (const key in object) {
5+
if (object.hasOwnProperty(key)) {
6+
// since we're dealing just with JSON this simple check should be enough
7+
if (object[key] instanceof Object) {
8+
if (!target[key]) {
9+
target[key] = {};
10+
}
11+
// recursivly merge into the target
12+
// most translations only run 3 or 4 levels deep, so no stack explosions
13+
target[key] = merge(target[key], object[key]);
14+
} else {
15+
target[key] = object[key];
16+
}
17+
}
18+
}
19+
}
20+
return target;
21+
};

0 commit comments

Comments
 (0)