Skip to content

Commit 3a49df7

Browse files
committed
feat(i18n): add simple i18n service
1 parent 6fc37f3 commit 3a49df7

16 files changed

+96
-39
lines changed

src/banner/banner.component.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import {
1010

1111
import { BannerService } from "./banner.service";
1212
import { NotificationContent } from "./banner-content.interface";
13-
14-
const EN = require("./../i18n/en.json");
13+
import { I18n } from "./../i18n/i18n.module";
1514

1615
/**
1716
* Banner messages are displayed toward the top of the UI and do not interrupt user’s work.
@@ -76,11 +75,11 @@ export class Banner implements OnInit {
7675

7776
@ViewChild("banner") banner;
7877

79-
constructor(protected bannerService: BannerService) {}
78+
constructor(protected bannerService: BannerService, protected i18n: I18n) {}
8079

8180
ngOnInit() {
8281
if (!this.bannerObj.closeLabel) {
83-
this.bannerObj.closeLabel = EN.BANNER.CLOSE_BUTTON;
82+
this.bannerObj.closeLabel = this.i18n.get().BANNER.CLOSE_BUTTON;
8483
}
8584
}
8685

src/banner/banner.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { StaticIconModule } from "./../icon/static-icon.module";
66
import { Toast } from "./toast.component";
77
import { Banner } from "./banner.component";
88
import { BannerService } from "./banner.service";
9+
import { I18nModule } from "./../i18n/i18n.module";
910

1011
export { BannerService } from "./banner.service";
1112
export { Banner } from "./banner.component";
@@ -21,7 +22,7 @@ export { Toast } from "./toast.component";
2122
Toast
2223
],
2324
entryComponents: [Banner, Toast],
24-
imports: [CommonModule, StaticIconModule],
25+
imports: [CommonModule, StaticIconModule, I18nModule],
2526
providers: [BannerService]
2627
})
2728
export class BannerModule {}

src/banner/toast.component.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import { BannerService } from "./banner.service";
44
import { ToastContent } from "./banner-content.interface";
55
import { Banner } from "./banner.component";
66

7-
const EN = require("./../i18n/en.json");
8-
97
/**
108
* Banner messages are displayed toward the top of the UI and do not interrupt user’s work.
119
*
@@ -55,7 +53,7 @@ export class Toast extends Banner implements OnInit {
5553

5654
ngOnInit() {
5755
if (!this.bannerObj.closeLabel) {
58-
this.bannerObj.closeLabel = EN.BANNER.CLOSE_BUTTON;
56+
this.bannerObj.closeLabel = this.i18n.get().BANNER.CLOSE_BUTTON;
5957
}
6058
}
6159
}

src/dialog/dialog.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { OverflowMenu } from "./overflow-menu/overflow-menu.component";
1818
import { OverflowMenuPane } from "./overflow-menu/overflow-menu-pane.component";
1919
import { OverflowMenuDirective } from "./overflow-menu/overflow-menu.directive";
2020
import { OverflowMenuOption } from "./overflow-menu/overflow-menu-option.component";
21+
import { I18nModule } from "./../i18n/i18n.module";
2122

2223
// exports
2324
export { DialogService } from "./dialog.service";
@@ -81,6 +82,6 @@ export const DIALOG_PLACEHOLDER_SERVICE_PROVIDER = {
8182
Tooltip,
8283
OverflowMenuPane
8384
],
84-
imports: [CommonModule, StaticIconModule]
85+
imports: [CommonModule, StaticIconModule, I18nModule]
8586
})
8687
export class DialogModule {}

src/dialog/overflow-menu/overflow-menu-pane.component.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { Component, ViewChild, HostListener } from "@angular/core";
1+
import { Component, ViewChild, HostListener, ElementRef } from "@angular/core";
22
import { Dialog } from "../dialog.component";
33
import { position } from "../../utils/position";
44
import { isFocusInLastItem, isFocusInFirstItem } from "./../../common/tab.service";
5-
6-
const EN = require("./../../i18n/en.json");
5+
import { I18n } from "./../../i18n/i18n.module";
76

87
/**
98
* Extend the `Dialog` component to create an overflow menu.
@@ -28,6 +27,10 @@ const EN = require("./../../i18n/en.json");
2827
export class OverflowMenuPane extends Dialog {
2928
@ViewChild("dialog") dialog;
3029

30+
constructor(protected elementRef: ElementRef, protected i18n: I18n) {
31+
super(elementRef);
32+
}
33+
3134
onDialogInit() {
3235
/**
3336
* -20 shifts the menu up to compensate for the
@@ -40,7 +43,7 @@ export class OverflowMenuPane extends Dialog {
4043
this.addGap["bottom"] = pos => position.addOffset(pos, -20, 60);
4144

4245
if (!this.dialogConfig.menuLabel) {
43-
this.dialogConfig.menuLabel = EN.OVERFLOW_MENU.OVERFLOW;
46+
this.dialogConfig.menuLabel = this.i18n.get().OVERFLOW_MENU.OVERFLOW;
4447
}
4548

4649
setTimeout(() => this.listItems()[0].focus());

src/dialog/overflow-menu/overflow-menu.component.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Component, ElementRef, Input } from "@angular/core";
2-
3-
const EN = require("./../../i18n/en.json");
2+
import { I18n } from "./../../i18n/i18n.module";
43

54
/**
65
* The OverFlow menu component encapsulates the OverFlowMenu directive, and the menu iconography into one convienent component
@@ -46,9 +45,9 @@ const EN = require("./../../i18n/en.json");
4645
})
4746
export class OverflowMenu {
4847

49-
@Input() buttonLabel = EN.OVERFLOW_MENU.OVERFLOW;
48+
@Input() buttonLabel = this.i18n.get().OVERFLOW_MENU.OVERFLOW;
5049

51-
constructor(private elementRef: ElementRef) {}
50+
constructor(protected elementRef: ElementRef, protected i18n: I18n) {}
5251

5352
get open() {
5453
if (this.elementRef.nativeElement.children[0].getAttribute("aria-expanded") === "true") {

src/dropdown/dropdown.component.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ import { throttleTime } from "rxjs/operators";
1919

2020
import { AbstractDropdownView } from "./abstract-dropdown-view.class";
2121
import { position } from "../utils/position";
22-
23-
const EN = require("./../i18n/en.json");
22+
import { I18n } from "./../i18n/i18n.module";
2423

2524
/**
2625
* Drop-down lists enable users to select one or more items from a list.
@@ -116,10 +115,16 @@ export class Dropdown implements OnInit, AfterContentInit, OnDestroy {
116115
* @memberof Dropdown
117116
*/
118117
@Input() scrollableContainer: string;
119-
120-
@Input() menuButtonLabel = EN.DROPDOWN.OPEN;
121-
122-
@Input() selectedLabel = EN.DROPDOWN.SELECTED;
118+
/**
119+
* Accessible label for the button that opens the dropdown list.
120+
* Defaults to the `DROPDOWN.OPEN` value from the i18n service.
121+
*/
122+
@Input() menuButtonLabel = this.i18n.get().DROPDOWN.OPEN;
123+
/**
124+
* Provides the label for the "# selected" text.
125+
* Defaults to the `DROPDOWN.SELECTED` value from the i18n service.
126+
*/
127+
@Input() selectedLabel = this.i18n.get().DROPDOWN.SELECTED;
123128
/**
124129
* Emits selection events.
125130
* @type {EventEmitter<Object>}
@@ -196,7 +201,7 @@ export class Dropdown implements OnInit, AfterContentInit, OnDestroy {
196201
* @param {TranslateService} translate
197202
* @memberof Dropdown
198203
*/
199-
constructor(private elementRef: ElementRef) {}
204+
constructor(protected elementRef: ElementRef, protected i18n: I18n) {}
200205

201206
/**
202207
* Updates the `type` property in the `@ContentChild`.

src/dropdown/dropdown.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Dropdown } from "./dropdown.component";
77
import { DropdownList } from "./list/dropdown-list.component";
88

99
import { ScrollableList } from "./scrollable-list.directive";
10+
import { I18nModule } from "./../i18n/i18n.module";
1011

1112
export { Dropdown } from "./dropdown.component";
1213
export { DropdownList } from "./list/dropdown-list.component";
@@ -29,7 +30,8 @@ export { ListItem } from "./list-item.interface";
2930
imports: [
3031
CommonModule,
3132
FormsModule,
32-
StaticIconModule
33+
StaticIconModule,
34+
I18nModule
3335
]
3436
})
3537
export class DropdownModule {}

src/i18n/i18n.module.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { NgModule, SkipSelf, Optional } from "@angular/core";
2+
3+
import { I18n } from "./i18n.service";
4+
5+
export { I18n } from "./i18n.service";
6+
7+
// either provides a new instance of ModalPlaceholderService, or returns the parent
8+
export function I18N_SERVICE_PROVIDER_FACTORY(parentService: I18n) {
9+
return parentService || new I18n();
10+
}
11+
12+
// placholder service *must* be a singleton to ensure the placeholder viewref is accessible globally
13+
export const I18N_SERVICE_PROVIDER = {
14+
provide: I18n,
15+
deps: [[new Optional(), new SkipSelf(), I18n]],
16+
useFactory: I18N_SERVICE_PROVIDER_FACTORY
17+
};
18+
19+
@NgModule({
20+
providers: [
21+
I18n,
22+
I18N_SERVICE_PROVIDER
23+
]
24+
})
25+
export class I18nModule {}

src/i18n/i18n.service.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Injectable } from "@angular/core";
2+
3+
const EN = require("./en.json");
4+
5+
@Injectable()
6+
export class I18n {
7+
private translationStrings = EN;
8+
9+
public set(strings) {
10+
this.translationStrings = Object.assign({}, EN, strings);
11+
}
12+
13+
public get() {
14+
return this.translationStrings;
15+
}
16+
}

0 commit comments

Comments
 (0)