diff --git a/.circleci/config.yml b/.circleci/config.yml index 551ff1f..b28c5c6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,11 @@ jobs: # deps already installed in image - checkout + - run: + # TODO - Remove when merge into master + name: install dependencies + command: npm install + - run: name: debug environment command: ionic info diff --git a/package.json b/package.json index 8b9ca4c..1725d60 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,8 @@ "@ionic-native/splash-screen": "4.4.0", "@ionic-native/status-bar": "4.4.0", "@ionic/storage": "2.1.3", + "@ngx-translate/core": "9.0.1", + "@ngx-translate/http-loader": "2.0.0", "cordova-android": "6.4.0", "cordova-browser": "5.0.1", "cordova-ios": "4.5.4", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 543bd81..7ffd4a4 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,7 +1,8 @@ import { Component, ViewChild } from '@angular/core'; -import { Platform, MenuController, Nav } from 'ionic-angular'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; +import { TranslateService } from '@ngx-translate/core'; +import { Platform, MenuController, Nav } from 'ionic-angular'; import { ClickerList, Page2 } from '../pages'; @Component({ @@ -15,6 +16,7 @@ export class ClickerApp { private platform: Platform; private splash: SplashScreen; private status: StatusBar; + private translateService: TranslateService; // make ClcikerList the root (or first) page public rootPage: any = ClickerList; @@ -25,24 +27,29 @@ export class ClickerApp { menu: MenuController, splash: SplashScreen, status: StatusBar, + translateService: TranslateService, ) { this.menu = menu; this.platform = platform; this.splash = splash; this.status = status; + this.translateService = translateService; this.initializeApp(); // set our app's pages this.pages = [ - { title: 'Clickers', component: ClickerList }, - { title: 'Goodbye Ionic', component: Page2 }, + { title: 'MENU.CLICKERS', component: ClickerList }, + { title: 'MENU.PAGE2', component: Page2 }, ]; } - private initializeApp(): void { - this.platform.ready().then(() => { + private initializeApp(): Promise { + return this.platform.ready().then(() => { + this.translateService.setDefaultLang('en'); + this.translateService.use('en'); + // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. this.status.styleDefault(); diff --git a/src/app/app.html b/src/app/app.html index 5c20128..3622017 100644 --- a/src/app/app.html +++ b/src/app/app.html @@ -2,14 +2,14 @@ - Pages + {{'MENU.TITLE' | translate}} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 9e12a23..b023f09 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,12 +1,19 @@ import { NgModule, ErrorHandler } from '@angular/core'; +import { HttpClient, HttpClientModule } from '@angular/common/http'; import { BrowserModule } from '@angular/platform-browser'; -import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateHttpLoader } from '@ngx-translate/http-loader'; +import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular'; import { ClickerApp } from './app.component'; import { ClickerList, PagesModule, Page2 } from '../pages'; import { ClickersService, StorageService } from '../services'; +export function createTranslateLoader(http: HttpClient): TranslateHttpLoader { + return new TranslateHttpLoader(http, './assets/i18n/', '.json'); +} + @NgModule({ declarations: [ ClickerApp, @@ -15,6 +22,14 @@ import { ClickersService, StorageService } from '../services'; BrowserModule, PagesModule, IonicModule.forRoot(ClickerApp), + HttpClientModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: (createTranslateLoader), + deps: [HttpClient], + }, + }), ], bootstrap: [IonicApp], entryComponents: [ diff --git a/src/app/app.spec.ts b/src/app/app.spec.ts index 9a9e3ba..fd799eb 100644 --- a/src/app/app.spec.ts +++ b/src/app/app.spec.ts @@ -1,5 +1,6 @@ import { ClickerApp } from './app.component'; import { MenuMock, PlatformMock, StatusBarMock, SplashScreenMock } from 'ionic-mocks'; +import { TranslateServiceMock } from '../services/translate.mock'; import { Page2 } from '../pages'; let instance: ClickerApp = null; @@ -7,7 +8,13 @@ let instance: ClickerApp = null; describe('ClickerApp', () => { beforeEach(() => { - instance = new ClickerApp(( PlatformMock.instance()), ( MenuMock.instance()), (SplashScreenMock.instance()), (StatusBarMock.instance())); + instance = new ClickerApp( + ( PlatformMock.instance()), + ( MenuMock.instance()), + (SplashScreenMock.instance()), + (StatusBarMock.instance()), + (new TranslateServiceMock()), + ); // ionic-mocks have lost the nav mock instance.nav = ({}); diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json new file mode 100644 index 0000000..3492bb1 --- /dev/null +++ b/src/assets/i18n/en.json @@ -0,0 +1,26 @@ +{ + "BUTTON": { + "OK": "Ok", + "OK_ADVANCED": "More Advanced Ok", + "DISMISS": "Dismiss", + "SHOW_SIMPLE": "Show Simple Alert", + "SHOW_ADVANCED": "Show More Advanced Alert" + }, + "ERROR": {}, + "PLACEHOLDER": { + "CLICKER_NAME": "New Clicker" + }, + "MENU": { + "TITLE": "Pages", + "PAGE2": "Goodbye Ionic", + "CLICKERS": "Clickers" + }, + "TITLE": { + "ALERT_SIMPLE": "This is an example for an alert", + "ALERT_ADVANCED": "This is an example for an alert", + "CLICKER_LIST": "Clickers", + "PAGE2": "Page 2" + }, + "LABEL": {}, + "CONTENT": {} +} diff --git a/src/components/clickerForm/clickerForm.html b/src/components/clickerForm/clickerForm.html index e60713d..1025a1e 100644 --- a/src/components/clickerForm/clickerForm.html +++ b/src/components/clickerForm/clickerForm.html @@ -2,7 +2,7 @@ - + diff --git a/src/components/components.module.ts b/src/components/components.module.ts index e7aaedc..cb922f2 100644 --- a/src/components/components.module.ts +++ b/src/components/components.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; import { ClickerButton } from './clickerButton/clickerButton'; import { ClickerForm } from './clickerForm/clickerForm'; @@ -13,6 +14,7 @@ import { ClickerForm } from './clickerForm/clickerForm'; FormsModule, IonicModule, ReactiveFormsModule, + TranslateModule, ], exports: [ ClickerButton, diff --git a/src/pages/clickerList/clickerList.html b/src/pages/clickerList/clickerList.html index 9cae7c0..9504ed9 100644 --- a/src/pages/clickerList/clickerList.html +++ b/src/pages/clickerList/clickerList.html @@ -3,7 +3,7 @@ - {{title}} + {{title | translate}} diff --git a/src/pages/clickerList/clickerList.ts b/src/pages/clickerList/clickerList.ts index f1e7adf..106e49e 100644 --- a/src/pages/clickerList/clickerList.ts +++ b/src/pages/clickerList/clickerList.ts @@ -9,12 +9,11 @@ import { ClickersService } from '../../services'; export class ClickerList { public clickerService: ClickersService; - public title: string; + public title: string = 'TITLE.CLICKER_LIST'; private nav: NavController; constructor(nav: NavController, clickerService: ClickersService) { this.nav = nav; this.clickerService = clickerService; - this.title = 'Clickers'; } } diff --git a/src/pages/page2/page2.html b/src/pages/page2/page2.html index 1056322..8dc2bca 100644 --- a/src/pages/page2/page2.html +++ b/src/pages/page2/page2.html @@ -3,11 +3,11 @@ - {{title}} + {{title | translate}} - - + + diff --git a/src/pages/page2/page2.spec.ts b/src/pages/page2/page2.spec.ts index 4bcf5c2..5f52bfb 100644 --- a/src/pages/page2/page2.spec.ts +++ b/src/pages/page2/page2.spec.ts @@ -1,8 +1,22 @@ import { async, fakeAsync, tick, ComponentFixture, TestBed } from '@angular/core/testing'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { App, Config, Form, IonicModule, Keyboard, DomController, MenuController, NavController, Platform, AlertController } from 'ionic-angular'; -import { AlertControllerMock, ConfigMock, PlatformMock } from 'ionic-mocks'; -import { Page2 } from './page2'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { + App, + Config, + Form, + IonicModule, + Keyboard, + DomController, + MenuController, + NavController, + Platform, + AlertController, +} from 'ionic-angular'; +import { AlertControllerMock, ConfigMock, PlatformMock } from 'ionic-mocks'; +import { TranslateServiceMock } from '../../services/translate.mock'; +import { TranslatePipeMock } from '../../pipes/translate.pipe.mock'; +import { Page2 } from './page2'; let fixture: ComponentFixture = null; let instance: any = null; @@ -16,12 +30,13 @@ describe('Pages: Page2', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [Page2], + declarations: [Page2, TranslatePipeMock], providers: [ App, DomController, Form, Keyboard, MenuController, NavController, {provide: Config, useFactory: () => ConfigMock.instance()}, {provide: Platform, useFactory: () => PlatformMock.instance()}, {provide: AlertController, useFactory: () => AlertControllerMock.instance()}, + {provide: TranslateService, useClass: TranslateServiceMock}, ], imports: [ FormsModule, diff --git a/src/pages/page2/page2.ts b/src/pages/page2/page2.ts index 2ed0541..dce8895 100644 --- a/src/pages/page2/page2.ts +++ b/src/pages/page2/page2.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { Alert, AlertController } from 'ionic-angular'; +import { TranslateService } from '@ngx-translate/core'; @Component({ templateUrl: './page2.html', @@ -12,13 +13,23 @@ export class Page2 { public okEd: boolean; public alert1: Alert; public alertController: AlertController; + public translateService: TranslateService; + public i18ns: object; + public title: string = 'TITLE.PAGE2'; - constructor(alertController: AlertController) { + constructor(alertController: AlertController, translateService: TranslateService) { + this.title = 'TITLE.PAGE2'; this.alertController = alertController; + this.translateService = translateService; + translateService.get(['BUTTON.OK', + 'BUTTON.OK_ADVANCED', + 'BUTTON.DISMISS', + 'TITLE.ALERT_SIMPLE', + 'TITLE.ALERT_ADVANCED', + ]) + .subscribe(i18ns => this.i18ns = i18ns); } - public title: string = 'Page 2'; - public onGainChange(): void { return; } @@ -26,8 +37,8 @@ export class Page2 { public showSimpleAlert(): any { this.alert1 = this.alertController.create({ - title: 'This is an example for an alert', - buttons: ['Ok', 'Dismiss'], + title: this.i18ns['TITLE.ALERT_SIMPLE'], + buttons: [this.i18ns['BUTTON.OK'], this.i18ns['BUTTON.DISMISS']], }); this.alert1.present(); @@ -36,12 +47,12 @@ export class Page2 { public showMoreAdvancedAlert(): any { this.alert1 = this.alertController.create({ - title: 'This is an example for an alert', + title: this.i18ns['TITLE.ALERT_ADVANCED'], buttons: [{ - text: 'More Advanced Ok', + text: this.i18ns['BUTTON.OK_ADVANCED'], handler: this.OK, } - , 'Dismiss'], + , this.i18ns['BUTTON.DISMISS']], }); this.alert1.present(); diff --git a/src/pages/pages.module.ts b/src/pages/pages.module.ts index 2127f5c..f621f21 100644 --- a/src/pages/pages.module.ts +++ b/src/pages/pages.module.ts @@ -1,4 +1,5 @@ import { NgModule } from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; import { IonicModule } from 'ionic-angular'; import { ComponentsModule } from '../components'; import { ClickerList } from './clickerList/clickerList'; @@ -9,7 +10,7 @@ import { Page2 } from './page2/page2'; ClickerList, Page2, ], - imports: [ IonicModule, ComponentsModule ], + imports: [ IonicModule, ComponentsModule, TranslateModule ], exports: [ ClickerList, // Page2, diff --git a/src/pipes/translate.pipe.mock.ts b/src/pipes/translate.pipe.mock.ts new file mode 100644 index 0000000..7c059aa --- /dev/null +++ b/src/pipes/translate.pipe.mock.ts @@ -0,0 +1,8 @@ +import { Pipe } from '@angular/core'; + +@Pipe({name: 'translate'}) +export class TranslatePipeMock { + public transform(): string { + return ''; + } +} diff --git a/src/services/mocks.ts b/src/services/mocks.ts index 851dcb2..94b9b3a 100644 --- a/src/services/mocks.ts +++ b/src/services/mocks.ts @@ -1,2 +1,3 @@ export * from './clickers.mock'; export * from './storage.mock'; +export * from './translate.mock'; diff --git a/src/services/translate.mock.ts b/src/services/translate.mock.ts new file mode 100644 index 0000000..6227c8a --- /dev/null +++ b/src/services/translate.mock.ts @@ -0,0 +1,14 @@ +import {Observable} from 'rxjs'; + +export class TranslateServiceMock { + + public get(value: any): Observable { + return Observable.of(value); + } + + /* tslint:disable */ + public use(value: any): void {} + public set(lang: string): void {} + public setDefaultLang(lang: string): void {} + /* tslint:enable */ +}