Skip to content

Commit

Permalink
feat(module): modularize everything and adding forChild
Browse files Browse the repository at this point in the history
  • Loading branch information
ocombe committed Jan 24, 2017
1 parent 4cb21a8 commit de2d56c
Show file tree
Hide file tree
Showing 13 changed files with 397 additions and 296 deletions.
56 changes: 44 additions & 12 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import {NgModule, ModuleWithProviders} from "@angular/core";
import {TranslatePipe} from "./src/translate.pipe";
import {TranslateParser, DefaultTranslateParser} from "./src/translate.parser";
import {TranslateService, TranslateLoader} from "./src/translate.service";
import {NgModule, ModuleWithProviders, Provider} from "@angular/core";
import {TranslateStore} from "./src/translate.store";
import {TranslateLoader, TranslateFakeLoader} from "./src/translate.loader";
import {TranslateService} from "./src/translate.service";
import {MissingTranslationHandler, FakeMissingTranslationHandler} from "./src/missing-translation-handler";
import {TranslateParser, TranslateDefaultParser} from "./src/translate.parser";
import {TranslateDirective} from "./src/translate.directive";
import {TranslatePipe} from "./src/translate.pipe";

export * from "./src/translate.pipe";
export * from "./src/translate.store";
export * from "./src/translate.loader";
export * from "./src/translate.service";
export * from "./src/missing-translation-handler";
export * from "./src/translate.parser";
export * from "./src/translate.directive";
export * from "./src/translate.pipe";

export interface TranslateModuleConfig {
loader?: Provider;
parser?: Provider;
missingTranslationHandler?: Provider;
}

@NgModule({
declarations: [
Expand All @@ -20,16 +32,36 @@ export * from "./src/translate.directive";
]
})
export class TranslateModule {
static forRoot(providedLoader: any = {
provide: TranslateLoader,
useFactory: () => {}
}): ModuleWithProviders {
/**
* Use this method in your root module to provide the TranslateService
* @param {TranslateModuleConfig} config
* @returns {ModuleWithProviders}
*/
static forRoot(config: TranslateModuleConfig = {}): ModuleWithProviders {
let baseConfig = this.forChild(config);
Array.prototype.push.call(baseConfig.providers, TranslateStore);
return baseConfig;
}

/**
* Use this method in your other (non root) modules to import the directive/pipe
* @param {TranslateModuleConfig} config
* @returns {ModuleWithProviders}
*/
static forChild(config: TranslateModuleConfig = {}): ModuleWithProviders {
let optionalProviders: Provider[] = [];
if(config.missingTranslationHandler) {
Array.prototype.push.call(optionalProviders, config.missingTranslationHandler);
}

return {
ngModule: TranslateModule,
providers: [
providedLoader,
TranslateService,
{ provide: TranslateParser, useClass: DefaultTranslateParser }
config.loader || {provide: TranslateLoader, useClass: TranslateFakeLoader},
config.parser || {provide: TranslateParser, useClass: TranslateDefaultParser},
config.missingTranslationHandler || {provide: MissingTranslationHandler, useClass: FakeMissingTranslationHandler},
...optionalProviders,
TranslateService
]
};
}
Expand Down
49 changes: 49 additions & 0 deletions src/missing-translation-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {TranslateService} from "./translate.service";
import {Injectable} from "@angular/core";

export interface MissingTranslationHandlerParams {
/**
* the key that's missing in translation files
*
* @type {string}
*/
key: string;

/**
* an instance of the service that was unable to translate the key.
*
* @type {TranslateService}
*/
translateService: TranslateService;

/**
* interpolation params that were passed along for translating the given key.
*
* @type {Object}
*/
interpolateParams?: Object;
}

export abstract class MissingTranslationHandler {
/**
* A function that handles missing translations.
*
* @abstract
* @param {MissingTranslationHandlerParams} params context for resolving a missing translation
* @returns {any} a value or an observable
* If it returns a value, then this value is used.
* If it return an observable, the value returned by this observable will be used (except if the method was "instant").
* If it doesn't return then the key will be used as a value
*/
abstract handle(params: MissingTranslationHandlerParams): any;
}

/**
* This handler is just a placeholder that does nothing, in case you don't need a missing translation handler at all
*/
@Injectable()
export class FakeMissingTranslationHandler implements MissingTranslationHandler {
handle(params: MissingTranslationHandlerParams): string {
return params.key;
}
}
16 changes: 16 additions & 0 deletions src/translate.loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Observable} from "rxjs/Observable";
import {Injectable} from "@angular/core";

export abstract class TranslateLoader {
abstract getTranslation(lang: string): Observable<any>;
}

/**
* This loader is just a placeholder that does nothing, in case you don't need a loader at all
*/
@Injectable()
export class TranslateFakeLoader extends TranslateLoader {
getTranslation(lang: string): Observable<any> {
return Observable.of({});
}
}
2 changes: 1 addition & 1 deletion src/translate.parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export abstract class TranslateParser {
}

@Injectable()
export class DefaultTranslateParser extends TranslateParser {
export class TranslateDefaultParser extends TranslateParser {
templateMatcher: RegExp = /{{\s?([^{}\s]*)\s?}}/g;

public interpolate(expr: string, params?: any): string {
Expand Down
49 changes: 5 additions & 44 deletions src/translate.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Injectable, EventEmitter, Optional} from "@angular/core";
import {Injectable, EventEmitter} from "@angular/core";
import {Observable} from "rxjs/Observable";
import {Observer} from "rxjs/Observer";
import "rxjs/add/observable/of";
Expand All @@ -8,6 +8,8 @@ import "rxjs/add/operator/merge";
import "rxjs/add/operator/toArray";
import "rxjs/add/operator/take";

import {TranslateLoader} from "./translate.loader";
import {MissingTranslationHandler, MissingTranslationHandlerParams} from "./missing-translation-handler";
import {TranslateParser} from "./translate.parser";
import {isDefined} from "./util";

Expand All @@ -26,52 +28,11 @@ export interface DefaultLangChangeEvent {
translations: any;
}

export interface MissingTranslationHandlerParams {
/**
* the key that's missing in translation files
*
* @type {string}
*/
key: string;

/**
* an instance of the service that was unable to translate the key.
*
* @type {TranslateService}
*/
translateService: TranslateService;

/**
* interpolation params that were passed along for translating the given key.
*
* @type {Object}
*/
interpolateParams?: Object;
}

declare interface Window {
navigator: any;
}
declare const window: Window;

export abstract class MissingTranslationHandler {
/**
* A function that handles missing translations.
*
* @abstract
* @param {MissingTranslationHandlerParams} params context for resolving a missing translation
* @returns {any} a value or an observable
* If it returns a value, then this value is used.
* If it return an observable, the value returned by this observable will be used (except if the method was "instant").
* If it doesn't return then the key will be used as a value
*/
abstract handle(params: MissingTranslationHandlerParams): any;
}

export abstract class TranslateLoader {
abstract getTranslation(lang: string): Observable<any>;
}

@Injectable()
export class TranslateService {
/**
Expand Down Expand Up @@ -120,7 +81,7 @@ export class TranslateService {
*/
constructor(public currentLoader: TranslateLoader,
public parser: TranslateParser,
@Optional() private missingTranslationHandler: MissingTranslationHandler) {
public missingTranslationHandler: MissingTranslationHandler) {
}

/**
Expand Down Expand Up @@ -312,7 +273,7 @@ export class TranslateService {
res = this.parser.interpolate(this.parser.getValue(this.translations[this.defaultLang], key), interpolateParams);
}

if(!res && this.missingTranslationHandler) {
if(typeof res === "undefined") {
let params: MissingTranslationHandlerParams = {key, translateService: this};
if(typeof interpolateParams !== 'undefined') {
params.interpolateParams = interpolateParams;
Expand Down
3 changes: 3 additions & 0 deletions src/translate.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class TranslateStore {

}
Loading

0 comments on commit de2d56c

Please sign in to comment.