File tree Expand file tree Collapse file tree 3 files changed +32
-2
lines changed
Expand file tree Collapse file tree 3 files changed +32
-2
lines changed Original file line number Diff line number Diff line change 11import { Injectable } from "@angular/core" ;
22import { BehaviorSubject } from "rxjs" ;
33import { map } from "rxjs/operators" ;
4+ import { merge } from "./../utils/object" ;
45
56const 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 ) ) ;
Original file line number Diff line number Diff 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} ) ;
Original file line number Diff line number Diff line change 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+ } ;
You can’t perform that action at this time.
0 commit comments